diff options
Diffstat (limited to 'src/builtin.cpp')
-rw-r--r-- | src/builtin.cpp | 3757 |
1 files changed, 1382 insertions, 2375 deletions
diff --git a/src/builtin.cpp b/src/builtin.cpp index 6a1bcc4d..336f09eb 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -1,186 +1,156 @@ -/** \file builtin.c - Functions for executing builtin functions. +// Functions for executing builtin functions. +// +// How to add a new builtin function: +// +// 1). Create a function in builtin.c with the following signature: +// +// <tt>static int builtin_NAME( parser_t &parser, wchar_t ** args )</tt> +// +// where NAME is the name of the builtin, and args is a zero-terminated list of arguments. +// +// 2). Add a line like { L"NAME", &builtin_NAME, N_(L"Bla bla bla") }, to the builtin_data_t +// variable. The description is used by the completion system. Note that this array is sorted. +// +// 3). Create a file doc_src/NAME.txt, containing the manual for the builtin in Doxygen-format. +// Check the other builtin manuals for proper syntax. +// +// 4). Use 'git add doc_src/NAME.txt' to start tracking changes to the documentation file. +#include "config.h" // IWYU pragma: keep - How to add a new builtin function: - - 1). Create a function in builtin.c with the following signature: - - <tt>static int builtin_NAME( parser_t &parser, wchar_t ** args )</tt> - - where NAME is the name of the builtin, and args is a zero-terminated list of arguments. - - 2). Add a line like { L"NAME", &builtin_NAME, N_(L"Bla bla bla") }, to the builtin_data_t variable. The description is used by the completion system. Note that this array is sorted! - - 3). Create a file doc_src/NAME.txt, containing the manual for the builtin in Doxygen-format. Check the other builtin manuals for proper syntax. - - 4). Use 'git add doc_src/NAME.txt' to start tracking changes to the documentation file. - -*/ - -#include "config.h" // IWYU pragma: keep - -#include <stdlib.h> -#include <stdio.h> -#include <wchar.h> -#include <unistd.h> +#include <assert.h> #include <errno.h> -#include <sys/stat.h> #include <fcntl.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <signal.h> -#include <wctype.h> +#include <sys/stat.h> #include <time.h> -#include <stack> -#include <assert.h> +#include <unistd.h> +#include <wchar.h> +#include <wctype.h> #include <algorithm> #include <map> +#include <memory> // IWYU pragma: keep #include <string> #include <utility> -#include "fallback.h" // IWYU pragma: keep - -#include "wutil.h" #include "builtin.h" -#include "function.h" +#include "builtin_commandline.h" +#include "builtin_complete.h" +#include "builtin_jobs.h" +#include "builtin_printf.h" +#include "builtin_set.h" +#include "builtin_set_color.h" +#include "builtin_string.h" +#include "builtin_test.h" +#include "builtin_ulimit.h" +#include "common.h" #include "complete.h" -#include "proc.h" -#include "parser.h" -#include "reader.h" #include "env.h" -#include "wgetopt.h" -#include "tokenizer.h" -#include "input.h" -#include "intern.h" #include "event.h" -#include "signal.h" #include "exec.h" +#include "expand.h" +#include "fallback.h" // IWYU pragma: keep +#include "function.h" #include "highlight.h" +#include "history.h" +#include "input.h" +#include "intern.h" +#include "io.h" +#include "parse_constants.h" #include "parse_util.h" +#include "parser.h" #include "parser_keywords.h" -#include "expand.h" #include "path.h" -#include "history.h" -#include "parse_tree.h" -#include "parse_constants.h" +#include "proc.h" +#include "reader.h" +#include "signal.h" +#include "tokenizer.h" #include "wcstringutil.h" +#include "wgetopt.h" +#include "wutil.h" // IWYU pragma: keep -/** - The default prompt for the read command -*/ +// The default prompt for the read command. #define DEFAULT_READ_PROMPT L"set_color green; echo -n read; set_color normal; echo -n \"> \"" -/** - The mode name to pass to history and input -*/ - +// The mode name to pass to history and input. #define READ_MODE_NAME L"fish_read" -/** - The send stuff to foreground message -*/ -#define FG_MSG _( L"Send job %d, '%ls' to foreground\n" ) +// The send stuff to foreground message. +#define FG_MSG _(L"Send job %d, '%ls' to foreground\n") -/** - Datastructure to describe a builtin. -*/ -struct builtin_data_t -{ - /** - Name of the builtin - */ +/// Datastructure to describe a builtin. +struct builtin_data_t { + // Name of the builtin. const wchar_t *name; - /** - Function pointer tothe builtin implementation - */ + // Function pointer tothe builtin implementation. int (*func)(parser_t &parser, io_streams_t &streams, wchar_t **argv); - /** - Description of what the builtin does - */ + // Description of what the builtin does. const wchar_t *desc; bool operator<(const wcstring &) const; bool operator<(const builtin_data_t *) const; }; -bool builtin_data_t::operator<(const wcstring &other) const -{ +bool builtin_data_t::operator<(const wcstring &other) const { return wcscmp(this->name, other.c_str()) < 0; } -bool builtin_data_t::operator<(const builtin_data_t *other) const -{ +bool builtin_data_t::operator<(const builtin_data_t *other) const { return wcscmp(this->name, other->name) < 0; } -/** - Counts the number of non null pointers in the specified array -*/ -int builtin_count_args(const wchar_t * const * argv) -{ +/// Counts the number of non null pointers in the specified array. +int builtin_count_args(const wchar_t *const *argv) { int argc = 1; - while (argv[argc] != NULL) - { + while (argv[argc] != NULL) { argc++; } return argc; } -/** - This function works like wperror, but it prints its result into - the streams.err string instead of to stderr. Used by the builtin - commands. -*/ - -static void builtin_wperror(const wchar_t *s, io_streams_t &streams) -{ +/// This function works like wperror, but it prints its result into the streams.err string instead +/// to stderr. Used by the builtin commands. +void builtin_wperror(const wchar_t *s, io_streams_t &streams) { char *err = strerror(errno); - if (s != NULL) - { + if (s != NULL) { streams.err.append(s); streams.err.append(L": "); } - if (err != NULL) - { + if (err != NULL) { const wcstring werr = str2wcstring(err); streams.err.append(werr); streams.err.push_back(L'\n'); } } -/** - Count the number of times the specified character occurs in the specified string -*/ -static int count_char(const wchar_t *str, wchar_t c) -{ +/// Count the number of times the specified character occurs in the specified string. +static int count_char(const wchar_t *str, wchar_t c) { int res = 0; - for (; *str; str++) - { - res += (*str==c); + for (; *str; str++) { + res += (*str == c); } return res; } -wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t *name) -{ - /* This won't ever work if no_exec is set */ - if (no_exec) - return wcstring(); +wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t *name) { + // This won't ever work if no_exec is set. + if (no_exec) return wcstring(); wcstring_list_t lst; wcstring out; const wcstring name_esc = escape_string(name, 1); wcstring cmd = format_string(L"__fish_print_help %ls", name_esc.c_str()); - if (!streams.out_is_redirected && isatty(STDOUT_FILENO)) - { + if (!streams.out_is_redirected && isatty(STDOUT_FILENO)) { // since we're using a subshell, __fish_print_help can't tell we're in // a terminal. Tell it ourselves. int cols = common_get_width(); cmd = format_string(L"__fish_print_help --tty-width %d %ls", cols, name_esc.c_str()); } - if (exec_subshell(cmd, lst, false /* don't apply exit status */) >= 0) - { - for (size_t i=0; i<lst.size(); i++) - { + if (exec_subshell(cmd, lst, false /* don't apply exit status */) >= 0) { + for (size_t i = 0; i < lst.size(); i++) { out.append(lst.at(i)); out.push_back(L'\n'); } @@ -188,225 +158,151 @@ wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t return out; } -/** - Print help for the specified builtin. If \c b is sb_err, also print - the line information - - If \c b is the buffer representing standard error, and the help - message is about to be printed to an interactive screen, it may be - shortened to fit the screen. - - -*/ - -void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, output_stream_t &b) -{ - bool is_stderr = (&b == &streams.err); - if (is_stderr) - { +/// Print help for the specified builtin. If \c b is sb_err, also print the line information. +/// +/// If \c b is the buffer representing standard error, and the help message is about to be printed +/// to an interactive screen, it may be shortened to fit the screen. +void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, + output_stream_t &b) { + bool is_stderr = &b == &streams.err; + if (is_stderr) { b.append(parser.current_line()); } - + const wcstring h = builtin_help_get(parser, streams, cmd); - - if (!h.size()) - return; - + + if (!h.size()) return; + wchar_t *str = wcsdup(h.c_str()); - if (str) - { + if (str) { bool is_short = false; - if (is_stderr) - { - - /* - Interactive mode help to screen - only print synopsis if - the rest won't fit - */ - + if (is_stderr) { + // Interactive mode help to screen - only print synopsis if the rest won't fit. int screen_height, lines; - + screen_height = common_get_height(); lines = count_char(str, L'\n'); - if (! get_is_interactive() || (lines > 2*screen_height/3)) - { + if (!shell_is_interactive() || (lines > 2 * screen_height / 3)) { wchar_t *pos; - int cut=0; + int cut = 0; int i; - + is_short = true; - - /* - First move down 4 lines - */ - + + // First move down 4 lines. pos = str; - for (i=0; (i<4) && pos && *pos; i++) - { - pos = wcschr(pos+1, L'\n'); + for (i = 0; (i < 4) && pos && *pos; i++) { + pos = wcschr(pos + 1, L'\n'); } - - if (pos && *pos) - { - - /* - Then find the next empty line - */ - for (; *pos; pos++) - { - if (*pos == L'\n') - { + + if (pos && *pos) { + // Then find the next empty line. + for (; *pos; pos++) { + if (*pos == L'\n') { wchar_t *pos2; int is_empty = 1; - - for (pos2 = pos+1; *pos2; pos2++) - { - if (*pos2 == L'\n') - break; - - if (*pos2 != L'\t' && *pos2 !=L' ') - { + + for (pos2 = pos + 1; *pos2; pos2++) { + if (*pos2 == L'\n') break; + + if (*pos2 != L'\t' && *pos2 != L' ') { is_empty = 0; break; } } - if (is_empty) - { - /* - And cut it - */ - *(pos2+1)=L'\0'; + if (is_empty) { + // And cut it. + *(pos2 + 1) = L'\0'; cut = 1; break; } } } } - - /* - We did not find a good place to cut message to - shorten it - so we make sure we don't print - anything. - */ - if (!cut) - { + + // We did not find a good place to cut message to shorten it - so we make sure we + // don't print anything. + if (!cut) { *str = 0; } - } } - + b.append(str); - if (is_short) - { + if (is_short) { b.append_format(_(L"%ls: Type 'help %ls' for related documentation\n\n"), cmd, cmd); } - + free(str); } } - -/** - Perform error reporting for encounter with unknown option -*/ -static void builtin_unknown_option(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt) -{ +/// Perform error reporting for encounter with unknown option. +void builtin_unknown_option(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, + const wchar_t *opt) { streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, opt); builtin_print_help(parser, streams, cmd, streams.err); } -/** - Perform error reporting for encounter with missing argument -*/ -static void builtin_missing_argument(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt) -{ +/// Perform error reporting for encounter with missing argument. +void builtin_missing_argument(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, + const wchar_t *opt) { streams.err.append_format(BUILTIN_ERR_MISSING, cmd, opt); builtin_print_help(parser, streams, cmd, streams.err); } -/* - Here follows the definition of all builtin commands. The function - names are all on the form builtin_NAME where NAME is the name of the - builtin. so the function name for the builtin 'fg' is - 'builtin_fg'. - - A few builtins, including 'while', 'command' and 'builtin' are not - defined here as they are handled directly by the parser. (They are - not parsed as commands, instead they only alter the parser state) - - The builtins 'break' and 'continue' are so closely related that they - share the same implementation, namely 'builtin_break_continue. - - Several other builtins, including jobs, ulimit and set are so big - that they have been given their own file. These files are all named - 'builtin_NAME.c', where NAME is the name of the builtin. These files - are included directly below. - -*/ - - -#include "builtin_set.cpp" -#include "builtin_commandline.cpp" -#include "builtin_complete.cpp" -#include "builtin_ulimit.cpp" -#include "builtin_jobs.cpp" -#include "builtin_set_color.cpp" -#include "builtin_printf.cpp" - -/* builtin_test lives in builtin_test.cpp */ -int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv); - -/* builtin_string lives in builtin_string.cpp */ -int builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv); - -/** - List a single key binding. - Returns false if no binding with that sequence and mode exists. - */ -static bool builtin_bind_list_one(const wcstring &seq, const wcstring &bind_mode, io_streams_t &streams) -{ +// Here follows the definition of all builtin commands. The function names are all of the form +// builtin_NAME where NAME is the name of the builtin. so the function name for the builtin 'fg' is +// 'builtin_fg'. +// +// A few builtins, including 'while', 'command' and 'builtin' are not defined here as they are +// handled directly by the parser. (They are not parsed as commands, instead they only alter the +// parser state) +// +// The builtins 'break' and 'continue' are so closely related that they share the same +// implementation, namely 'builtin_break_continue. +// +// Several other builtins, including jobs, ulimit and set are so big that they have been given their +// own module. These files are all named 'builtin_NAME.cpp', where NAME is the name of the builtin. + +/// List a single key binding. +/// Returns false if no binding with that sequence and mode exists. +static bool builtin_bind_list_one(const wcstring &seq, const wcstring &bind_mode, + io_streams_t &streams) { std::vector<wcstring> ecmds; wcstring sets_mode; - if (!input_mapping_get(seq, bind_mode, &ecmds, &sets_mode)) - { + if (!input_mapping_get(seq, bind_mode, &ecmds, &sets_mode)) { return false; } streams.out.append(L"bind"); - // Append the mode flags if applicable - if (bind_mode != DEFAULT_BIND_MODE) - { + // Append the mode flags if applicable. + if (bind_mode != DEFAULT_BIND_MODE) { const wcstring emode = escape_string(bind_mode, ESCAPE_ALL); streams.out.append(L" -M "); streams.out.append(emode); } - if (sets_mode != bind_mode) - { + if (sets_mode != bind_mode) { const wcstring esets_mode = escape_string(sets_mode, ESCAPE_ALL); streams.out.append(L" -m "); streams.out.append(esets_mode); } - // Append the name + // Append the name. wcstring tname; - if (input_terminfo_get_name(seq, &tname)) - { - // Note that we show -k here because we have an input key name - streams.out.append_format( L" -k %ls", tname.c_str()); - } - else - { - // No key name, so no -k; we show the escape sequence directly + if (input_terminfo_get_name(seq, &tname)) { + // Note that we show -k here because we have an input key name. + streams.out.append_format(L" -k %ls", tname.c_str()); + } else { + // No key name, so no -k; we show the escape sequence directly. const wcstring eseq = escape_string(seq, ESCAPE_ALL); - streams.out.append_format( L" %ls", eseq.c_str()); + streams.out.append_format(L" %ls", eseq.c_str()); } - // Now show the list of commands - for (size_t i = 0; i < ecmds.size(); i++) - { + // Now show the list of commands. + for (size_t i = 0; i < ecmds.size(); i++) { const wcstring &ecmd = ecmds.at(i); const wcstring escaped_ecmd = escape_string(ecmd, ESCAPE_ALL); streams.out.push_back(' '); @@ -417,19 +313,13 @@ static bool builtin_bind_list_one(const wcstring &seq, const wcstring &bind_mode return true; } -/** - List all current key bindings - */ -static void builtin_bind_list(const wchar_t *bind_mode, io_streams_t &streams) -{ +/// List all current key bindings. +static void builtin_bind_list(const wchar_t *bind_mode, io_streams_t &streams) { const std::vector<input_mapping_name_t> lst = input_mapping_get_names(); for (std::vector<input_mapping_name_t>::const_iterator it = lst.begin(), end = lst.end(); - it != end; - ++it) - { - if (bind_mode != NULL && bind_mode != it->mode) - { + it != end; ++it) { + if (bind_mode != NULL && bind_mode != it->mode) { continue; } @@ -437,353 +327,259 @@ static void builtin_bind_list(const wchar_t *bind_mode, io_streams_t &streams) } } -/** - Print terminfo key binding names to string buffer used for standard output. - - \param all if set, all terminfo key binding names will be - printed. If not set, only ones that are defined for this terminal - are printed. - */ -static void builtin_bind_key_names(int all, io_streams_t &streams) -{ +/// Print terminfo key binding names to string buffer used for standard output. +/// +/// \param all if set, all terminfo key binding names will be printed. If not set, only ones that +/// are defined for this terminal are printed. +static void builtin_bind_key_names(int all, io_streams_t &streams) { const wcstring_list_t names = input_terminfo_get_names(!all); - for (size_t i=0; i<names.size(); i++) - { + for (size_t i = 0; i < names.size(); i++) { const wcstring &name = names.at(i); - streams.out.append_format( L"%ls\n", name.c_str()); + streams.out.append_format(L"%ls\n", name.c_str()); } } -/** - Print all the special key binding functions to string buffer used for standard output. - - */ -static void builtin_bind_function_names(io_streams_t &streams) -{ +/// Print all the special key binding functions to string buffer used for standard output. +static void builtin_bind_function_names(io_streams_t &streams) { wcstring_list_t names = input_function_get_names(); - for (size_t i=0; i<names.size(); i++) - { + for (size_t i = 0; i < names.size(); i++) { const wchar_t *seq = names.at(i).c_str(); - streams.out.append_format( L"%ls\n", seq); + streams.out.append_format(L"%ls\n", seq); } } -// Wraps input_terminfo_get_sequence(), appending the correct error messages as needed. -static int get_terminfo_sequence(const wchar_t *seq, wcstring *out_seq, io_streams_t &streams) -{ - if (input_terminfo_get_sequence(seq, out_seq)) - { +/// Wraps input_terminfo_get_sequence(), appending the correct error messages as needed. +static int get_terminfo_sequence(const wchar_t *seq, wcstring *out_seq, io_streams_t &streams) { + if (input_terminfo_get_sequence(seq, out_seq)) { return 1; } wcstring eseq = escape_string(seq, 0); - switch (errno) - { - case ENOENT: - { - streams.err.append_format(_(L"%ls: No key with name '%ls' found\n"), L"bind", eseq.c_str()); + switch (errno) { + case ENOENT: { + streams.err.append_format(_(L"%ls: No key with name '%ls' found\n"), L"bind", + eseq.c_str()); break; } - - case EILSEQ: - { - streams.err.append_format(_(L"%ls: Key with name '%ls' does not have any mapping\n"), L"bind", eseq.c_str()); + case EILSEQ: { + streams.err.append_format(_(L"%ls: Key with name '%ls' does not have any mapping\n"), + L"bind", eseq.c_str()); break; } - - default: - { - streams.err.append_format(_(L"%ls: Unknown error trying to bind to key named '%ls'\n"), L"bind", eseq.c_str()); + default: { + streams.err.append_format(_(L"%ls: Unknown error trying to bind to key named '%ls'\n"), + L"bind", eseq.c_str()); break; } } return 0; } -/** - Add specified key binding. - */ -static int builtin_bind_add(const wchar_t *seq, const wchar_t * const *cmds, size_t cmds_len, +/// Add specified key binding. +static int builtin_bind_add(const wchar_t *seq, const wchar_t *const *cmds, size_t cmds_len, const wchar_t *mode, const wchar_t *sets_mode, int terminfo, - io_streams_t &streams) -{ - - if (terminfo) - { + io_streams_t &streams) { + if (terminfo) { wcstring seq2; - if (get_terminfo_sequence(seq, &seq2, streams)) - { + if (get_terminfo_sequence(seq, &seq2, streams)) { input_mapping_add(seq2.c_str(), cmds, cmds_len, mode, sets_mode); - } - else - { + } else { return 1; } - } - else - { + } else { input_mapping_add(seq, cmds, cmds_len, mode, sets_mode); } return 0; - } -/** - Erase specified key bindings - - \param seq an array of all key bindings to erase - \param all if specified, _all_ key bindings will be erased - \param mode if specified, only bindings from that mode will be erased. If not given and \c all is \c false, \c DEFAULT_BIND_MODE will be used. - */ -static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int use_terminfo, io_streams_t &streams) -{ - if (all) - { +/// Erase specified key bindings +/// +/// \param seq an array of all key bindings to erase +/// \param all if specified, _all_ key bindings will be erased +/// \param mode if specified, only bindings from that mode will be erased. If not given and \c all +/// is \c false, \c DEFAULT_BIND_MODE will be used. +static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int use_terminfo, + io_streams_t &streams) { + if (all) { const std::vector<input_mapping_name_t> lst = input_mapping_get_names(); for (std::vector<input_mapping_name_t>::const_iterator it = lst.begin(), end = lst.end(); - it != end; - ++it) - { - if (mode == NULL || mode == it->mode) - { + it != end; ++it) { + if (mode == NULL || mode == it->mode) { input_mapping_erase(it->seq, it->mode); } } return 0; } - else - { - int res = 0; - - if (mode == NULL) mode = DEFAULT_BIND_MODE; - while (*seq) - { - if (use_terminfo) - { - wcstring seq2; - if (get_terminfo_sequence(*seq++, &seq2, streams)) - { - input_mapping_erase(seq2, mode); - } - else - { - res = 1; - } - } - else - { - input_mapping_erase(*seq++, mode); + int res = 0; + if (mode == NULL) mode = DEFAULT_BIND_MODE; + + while (*seq) { + if (use_terminfo) { + wcstring seq2; + if (get_terminfo_sequence(*seq++, &seq2, streams)) { + input_mapping_erase(seq2, mode); + } else { + res = 1; } + } else { + input_mapping_erase(*seq++, mode); } - - return res; } -} + return res; +} -/** - The bind builtin, used for setting character sequences -*/ -static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The bind builtin, used for setting character sequences. +static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; - enum - { - BIND_INSERT, - BIND_ERASE, - BIND_KEY_NAMES, - BIND_FUNCTION_NAMES - }; - - int argc=builtin_count_args(argv); + enum { BIND_INSERT, BIND_ERASE, BIND_KEY_NAMES, BIND_FUNCTION_NAMES }; + int argc = builtin_count_args(argv); int mode = BIND_INSERT; int res = STATUS_BUILTIN_OK; int all = 0; - const wchar_t *bind_mode = DEFAULT_BIND_MODE; bool bind_mode_given = false; const wchar_t *sets_bind_mode = DEFAULT_BIND_MODE; bool sets_bind_mode_given = false; - int use_terminfo = 0; - w.woptind=0; + w.woptind = 0; - static const struct woption long_options[] = - { - { L"all", no_argument, 0, 'a' }, - { L"erase", no_argument, 0, 'e' }, - { L"function-names", no_argument, 0, 'f' }, - { L"help", no_argument, 0, 'h' }, - { L"key", no_argument, 0, 'k' }, - { L"key-names", no_argument, 0, 'K' }, - { L"mode", required_argument, 0, 'M' }, - { L"sets-mode", required_argument, 0, 'm' }, - { 0, 0, 0, 0 } - }; + static const struct woption long_options[] = {{L"all", no_argument, 0, 'a'}, + {L"erase", no_argument, 0, 'e'}, + {L"function-names", no_argument, 0, 'f'}, + {L"help", no_argument, 0, 'h'}, + {L"key", no_argument, 0, 'k'}, + {L"key-names", no_argument, 0, 'K'}, + {L"mode", required_argument, 0, 'M'}, + {L"sets-mode", required_argument, 0, 'm'}, + {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"aehkKfM:m:", - long_options, - &opt_index); + int opt = w.wgetopt_long(argc, argv, L"aehkKfM:m:", long_options, &opt_index); - if (opt == -1) - break; + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; - - case 'a': + } + case 'a': { all = 1; break; - - case 'e': + } + case 'e': { mode = BIND_ERASE; break; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case 'k': + } + case 'k': { use_terminfo = 1; break; - - case 'K': + } + case 'K': { mode = BIND_KEY_NAMES; break; - - case 'f': + } + case 'f': { mode = BIND_FUNCTION_NAMES; break; - - case 'M': + } + case 'M': { bind_mode = w.woptarg; bind_mode_given = true; break; - - case 'm': + } + case 'm': { sets_bind_mode = w.woptarg; sets_bind_mode_given = true; break; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - - + } } } - /* - * if mode is given, but not new mode, default to new mode to mode - */ - if (bind_mode_given && !sets_bind_mode_given) - { + // if mode is given, but not new mode, default to new mode to mode. + if (bind_mode_given && !sets_bind_mode_given) { sets_bind_mode = bind_mode; } - switch (mode) - { - - case BIND_ERASE: - { - if (builtin_bind_erase(&argv[w.woptind], all, bind_mode_given ? bind_mode : NULL, use_terminfo, streams)) - { + switch (mode) { + case BIND_ERASE: { + if (builtin_bind_erase(&argv[w.woptind], all, bind_mode_given ? bind_mode : NULL, + use_terminfo, streams)) { res = STATUS_BUILTIN_ERROR; } break; } - - case BIND_INSERT: - { - switch (argc-w.woptind) - { - case 0: - { + case BIND_INSERT: { + switch (argc - w.woptind) { + case 0: { builtin_bind_list(bind_mode_given ? bind_mode : NULL, streams); break; } - - case 1: - { + case 1: { wcstring seq; - if (use_terminfo) - { - if (!get_terminfo_sequence(argv[w.woptind], &seq, streams)) - { + if (use_terminfo) { + if (!get_terminfo_sequence(argv[w.woptind], &seq, streams)) { res = STATUS_BUILTIN_ERROR; - // get_terminfo_sequence already printed the error + // get_terminfo_sequence already printed the error. break; } - } - else - { + } else { seq = argv[w.woptind]; } - if (!builtin_bind_list_one(seq, bind_mode, streams)) - { + if (!builtin_bind_list_one(seq, bind_mode, streams)) { res = STATUS_BUILTIN_ERROR; wcstring eseq = escape_string(argv[w.woptind], 0); - if (use_terminfo) - { - streams.err.append_format(_(L"%ls: No binding found for key '%ls'\n"), argv[0], eseq.c_str()); - } - else - { - streams.err.append_format(_(L"%ls: No binding found for sequence '%ls'\n"), argv[0], eseq.c_str()); + if (use_terminfo) { + streams.err.append_format(_(L"%ls: No binding found for key '%ls'\n"), + argv[0], eseq.c_str()); + } else { + streams.err.append_format( + _(L"%ls: No binding found for sequence '%ls'\n"), argv[0], + eseq.c_str()); } } break; } - - default: - { - if (builtin_bind_add(argv[w.woptind], argv + (w.woptind + 1), argc - (w.woptind + 1), bind_mode, sets_bind_mode, use_terminfo, streams)) - { + default: { + if (builtin_bind_add(argv[w.woptind], argv + (w.woptind + 1), + argc - (w.woptind + 1), bind_mode, sets_bind_mode, + use_terminfo, streams)) { res = STATUS_BUILTIN_ERROR; } break; } - } break; } - - case BIND_KEY_NAMES: - { + case BIND_KEY_NAMES: { builtin_bind_key_names(all, streams); break; } - - - case BIND_FUNCTION_NAMES: - { + case BIND_FUNCTION_NAMES: { builtin_bind_function_names(streams); break; } - - - default: - { + default: { res = STATUS_BUILTIN_ERROR; streams.err.append_format(_(L"%ls: Invalid state\n"), argv[0]); break; @@ -793,236 +589,156 @@ static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) return res; } - -/** - The block builtin, used for temporarily blocking events -*/ -static int builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The block builtin, used for temporarily blocking events. +static int builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; - enum - { + enum { UNSET, GLOBAL, LOCAL, - } - ; + }; - int scope=UNSET; + int scope = UNSET; int erase = 0; - int argc=builtin_count_args(argv); + int argc = builtin_count_args(argv); - w.woptind=0; + w.woptind = 0; - static const struct woption - long_options[] = - { - { - L"erase", no_argument, 0, 'e' - } - , - { - L"local", no_argument, 0, 'l' - } - , - { - L"global", no_argument, 0, 'g' - } - , - { - L"help", no_argument, 0, 'h' - } - , - { - 0, 0, 0, 0 - } - } - ; + static const struct woption long_options[] = {{L"erase", no_argument, 0, 'e'}, + {L"local", no_argument, 0, 'l'}, + {L"global", no_argument, 0, 'g'}, + {L"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - - int opt = w.wgetopt_long(argc, - argv, - L"elgh", - long_options, - &opt_index); - if (opt == -1) - break; - - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + int opt = w.wgetopt_long(argc, argv, L"elgh", long_options, &opt_index); + if (opt == -1) break; + + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); - return STATUS_BUILTIN_ERROR; - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case 'g': + } + case 'g': { scope = GLOBAL; break; - - case 'l': + } + case 'l': { scope = LOCAL; break; - - case 'e': + } + case 'e': { erase = 1; break; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } - if (erase) - { - if (scope != UNSET) - { - streams.err.append_format(_(L"%ls: Can not specify scope when removing block\n"), argv[0]); + if (erase) { + if (scope != UNSET) { + streams.err.append_format(_(L"%ls: Can not specify scope when removing block\n"), + argv[0]); return STATUS_BUILTIN_ERROR; } - if (parser.global_event_blocks.empty()) - { + if (parser.global_event_blocks.empty()) { streams.err.append_format(_(L"%ls: No blocks defined\n"), argv[0]); return STATUS_BUILTIN_ERROR; } parser.global_event_blocks.pop_front(); - } - else - { + } else { size_t block_idx = 0; block_t *block = parser.block_at_index(block_idx); event_blockage_t eb = {}; - eb.typemask = (1<<EVENT_ANY); + eb.typemask = (1 << EVENT_ANY); - switch (scope) - { - case LOCAL: - { + switch (scope) { + case LOCAL: { // If this is the outermost block, then we're global - if (block_idx + 1 >= parser.block_count()) - { + if (block_idx + 1 >= parser.block_count()) { block = NULL; } break; } - case GLOBAL: - { - block=NULL; + case GLOBAL: { + block = NULL; } - case UNSET: - { - while (block != NULL && block->type() != FUNCTION_CALL && block->type() != FUNCTION_CALL_NO_SHADOW) - { + case UNSET: { + while (block != NULL && block->type() != FUNCTION_CALL && + block->type() != FUNCTION_CALL_NO_SHADOW) { // Set it in function scope block = parser.block_at_index(++block_idx); } } } - if (block) - { + if (block) { block->event_blocks.push_front(eb); - } - else - { + } else { parser.global_event_blocks.push_front(eb); } } return STATUS_BUILTIN_OK; - } -/** - 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. -*/ -static int builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ - int argc=builtin_count_args(argv); - int list=0; +/// 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. +static int builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv) { + int argc = builtin_count_args(argv); + int list = 0; wgetopter_t w; - static const struct woption - long_options[] = - { - { - L"names", no_argument, 0, 'n' - } - , - { - L"help", no_argument, 0, 'h' - } - , - { - 0, 0, 0, 0 - } - } - ; + static const struct woption long_options[] = { + {L"names", no_argument, 0, 'n'}, {L"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"nh", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"nh", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); - - return STATUS_BUILTIN_ERROR; - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case 'n': - list=1; + } + case 'n': { + list = 1; break; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } - if (list) - { + if (list) { wcstring_list_t names = builtin_get_names(); sort(names.begin(), names.end()); - for (size_t i=0; i<names.size(); i++) - { + for (size_t i = 0; i < names.size(); i++) { const wchar_t *el = names.at(i).c_str(); streams.out.append(el); @@ -1032,64 +748,39 @@ static int builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **ar return STATUS_BUILTIN_OK; } -/** - Implementation of the builtin emit command, used to create events. - */ -static int builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// Implementation of the builtin emit command, used to create events. +static int builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; - int argc=builtin_count_args(argv); + int argc = builtin_count_args(argv); - static const struct woption - long_options[] = - { - { - L"help", no_argument, 0, 'h' - } - , - { - 0, 0, 0, 0 - } - } - ; + static const struct woption long_options[] = {{L"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"h", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"h", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } - if (!argv[w.woptind]) - { + if (!argv[w.woptind]) { streams.err.append_format(L"%ls: expected event name\n", argv[0]); return STATUS_BUILTIN_ERROR; } @@ -1100,438 +791,313 @@ static int builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv) return STATUS_BUILTIN_OK; } - -/** - Implementation of the builtin 'command'. Actual command running is handled by - the parser, this just processes the flags. -*/ -static int builtin_command(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// Implementation of the builtin 'command'. Actual command running is handled by the parser, this +/// just processes the flags. +static int builtin_command(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; - int argc=builtin_count_args(argv); - int print_path=0; + int argc = builtin_count_args(argv); + int print_path = 0; - w.woptind=0; + w.woptind = 0; - static const struct woption - long_options[] = - { - { L"search", no_argument, 0, 's' }, - { L"help", no_argument, 0, 'h' }, - { 0, 0, 0, 0 } - }; + static const struct woption long_options[] = { + {L"search", no_argument, 0, 's'}, {L"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"svh", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"svh", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - + } case 's': - case 'v': - print_path=1; + case 'v': { + print_path = 1; break; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } - if (!print_path) - { + if (!print_path) { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_ERROR; } - int found=0; + int found = 0; - for (int idx = w.woptind; argv[idx]; ++idx) - { + for (int idx = w.woptind; argv[idx]; ++idx) { const wchar_t *command_name = argv[idx]; wcstring path; - if (path_get_path(command_name, &path)) - { - streams.out.append_format( L"%ls\n", path.c_str()); + if (path_get_path(command_name, &path)) { + streams.out.append_format(L"%ls\n", path.c_str()); ++found; } } return found ? STATUS_BUILTIN_OK : STATUS_BUILTIN_ERROR; } -/** - 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) -{ +/// 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) { wgetopter_t w; - int argc=builtin_count_args(argv); + int argc = builtin_count_args(argv); - /* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */ - if (argc == 1) - { + // Hackish - if we have no arguments other than the command, we are a "naked invocation" and we + // just print help. + if (argc == 1) { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_ERROR; } - static const struct woption - long_options[] = - { - { L"help", no_argument, 0, 'h' }, - { 0, 0, 0, 0 } - }; + static const struct woption long_options[] = {{L"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"h", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"h", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } + return STATUS_BUILTIN_ERROR; } -/** - Return a definition of the specified function. Used by the functions builtin. -*/ -static wcstring functions_def(const wcstring &name) -{ - CHECK(! name.empty(), L""); +/// Return a definition of the specified function. Used by the functions builtin. +static wcstring functions_def(const wcstring &name) { + CHECK(!name.empty(), L""); wcstring out; - wcstring desc, def; function_get_desc(name, &desc); function_get_definition(name, &def); - event_t search(EVENT_ANY); - search.function_name = name; - std::vector<event_t *> ev; event_get(search, &ev); out.append(L"function "); - /* Typically we prefer to specify the function name first, e.g. "function foo --description bar" - But If the function name starts with a -, we'll need to output it after all the options. */ + // Typically we prefer to specify the function name first, e.g. "function foo --description bar" + // But If the function name starts with a -, we'll need to output it after all the options. bool defer_function_name = (name.at(0) == L'-'); - if (! defer_function_name) - { + if (!defer_function_name) { out.append(escape_string(name, true)); } - if (! desc.empty()) - { + if (!desc.empty()) { wcstring esc_desc = escape_string(desc, true); out.append(L" --description "); out.append(esc_desc); } - if (!function_get_shadows(name)) - { + if (function_get_shadow_builtin(name)) { + out.append(L" --shadow-builtin"); + } + + if (!function_get_shadow_scope(name)) { out.append(L" --no-scope-shadowing"); } - for (size_t i=0; i<ev.size(); i++) - { + for (size_t i = 0; i < ev.size(); i++) { event_t *next = ev.at(i); - switch (next->type) - { - case EVENT_SIGNAL: - { + switch (next->type) { + case EVENT_SIGNAL: { append_format(out, L" --on-signal %ls", sig2wcs(next->param1.signal)); break; } - - case EVENT_VARIABLE: - { + case EVENT_VARIABLE: { append_format(out, L" --on-variable %ls", next->str_param1.c_str()); break; } - - case EVENT_EXIT: - { + case EVENT_EXIT: { if (next->param1.pid > 0) append_format(out, L" --on-process-exit %d", next->param1.pid); else append_format(out, L" --on-job-exit %d", -next->param1.pid); break; } - - case EVENT_JOB_ID: - { + case EVENT_JOB_ID: { const job_t *j = job_get(next->param1.job_id); - if (j) - append_format(out, L" --on-job-exit %d", j->pgid); + if (j) append_format(out, L" --on-job-exit %d", j->pgid); break; } - - case EVENT_GENERIC: - { + case EVENT_GENERIC: { append_format(out, L" --on-event %ls", next->str_param1.c_str()); break; } - } - } - wcstring_list_t named = function_get_named_arguments(name); - if (! named.empty()) - { + if (!named.empty()) { append_format(out, L" --argument"); - for (size_t i=0; i < named.size(); i++) - { + for (size_t i = 0; i < named.size(); i++) { append_format(out, L" %ls", named.at(i).c_str()); } } - /* Output the function name if we deferred it */ - if (defer_function_name) - { + // Output the function name if we deferred it. + if (defer_function_name) { out.append(L" -- "); out.append(escape_string(name, true)); } - /* Output any inherited variables as `set -l` lines */ - std::map<wcstring,env_var_t> inherit_vars = function_get_inherit_vars(name); - for (std::map<wcstring,env_var_t>::const_iterator it = inherit_vars.begin(), end = inherit_vars.end(); it != end; ++it) - { + // Output any inherited variables as `set -l` lines. + std::map<wcstring, env_var_t> inherit_vars = function_get_inherit_vars(name); + for (std::map<wcstring, env_var_t>::const_iterator it = inherit_vars.begin(), + end = inherit_vars.end(); + it != end; ++it) { wcstring_list_t lst; - if (!it->second.missing()) - { + if (!it->second.missing()) { tokenize_variable_array(it->second, lst); } - /* This forced tab is crummy, but we don't know what indentation style the function uses */ + // This forced tab is crummy, but we don't know what indentation style the function uses. append_format(out, L"\n\tset -l %ls", it->first.c_str()); - for (wcstring_list_t::const_iterator arg_it = lst.begin(), arg_end = lst.end(); arg_it != arg_end; ++arg_it) - { + for (wcstring_list_t::const_iterator arg_it = lst.begin(), arg_end = lst.end(); + arg_it != arg_end; ++arg_it) { wcstring earg = escape_string(*arg_it, ESCAPE_ALL); out.push_back(L' '); out.append(earg); } } - /* This forced tab is sort of crummy - not all functions start with a tab */ + // This forced tab is sort of crummy - not all functions start with a tab. append_format(out, L"\n\t%ls", def.c_str()); - /* Append a newline before the 'end', unless there already is one there */ - if (! string_suffixes_string(L"\n", def)) - { + // Append a newline before the 'end', unless there already is one there. + if (!string_suffixes_string(L"\n", def)) { out.push_back(L'\n'); } out.append(L"end\n"); return out; } - -/** - The functions builtin, used for listing and erasing functions. -*/ -static int builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The functions builtin, used for listing and erasing functions. +static int builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; int i; - int erase=0; - wchar_t *desc=0; + int erase = 0; + wchar_t *desc = 0; - int argc=builtin_count_args(argv); - int list=0; - int show_hidden=0; + int argc = builtin_count_args(argv); + int list = 0; + int show_hidden = 0; int res = STATUS_BUILTIN_OK; int query = 0; int copy = 0; - static const struct woption - long_options[] = - { - { - L"erase", no_argument, 0, 'e' - } - , - { - L"description", required_argument, 0, 'd' - } - , - { - L"names", no_argument, 0, 'n' - } - , - { - L"all", no_argument, 0, 'a' - } - , - { - L"help", no_argument, 0, 'h' - } - , - { - L"query", no_argument, 0, 'q' - } - , - { - L"copy", no_argument, 0, 'c' - } - , - { - 0, 0, 0, 0 - } - } - ; + static const struct woption long_options[] = { + {L"erase", no_argument, 0, 'e'}, {L"description", required_argument, 0, 'd'}, + {L"names", no_argument, 0, 'n'}, {L"all", no_argument, 0, 'a'}, + {L"help", no_argument, 0, 'h'}, {L"query", no_argument, 0, 'q'}, + {L"copy", no_argument, 0, 'c'}, {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"ed:nahqc", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"ed:nahqc", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); - - return STATUS_BUILTIN_ERROR; - - case 'e': - erase=1; + } + case 'e': { + erase = 1; break; - - case 'd': - desc=w.woptarg; + } + case 'd': { + desc = w.woptarg; break; - - case 'n': - list=1; + } + case 'n': { + list = 1; break; - - case 'a': - show_hidden=1; + } + case 'a': { + show_hidden = 1; break; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case 'q': + } + case 'q': { query = 1; break; - - case 'c': + } + case 'c': { copy = 1; break; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } - /* - Erase, desc, query, copy and list are mutually exclusive - */ - if ((erase + (!!desc) + list + query + copy) > 1) - { - streams.err.append_format(_(L"%ls: Invalid combination of options\n"), - argv[0]); + // Erase, desc, query, copy and list are mutually exclusive. + if ((erase + (!!desc) + list + query + copy) > 1) { + streams.err.append_format(_(L"%ls: Invalid combination of options\n"), argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - if (erase) - { + if (erase) { int i; - for (i=w.woptind; i<argc; i++) - function_remove(argv[i]); + for (i = w.woptind; i < argc; i++) function_remove(argv[i]); return STATUS_BUILTIN_OK; - } - else if (desc) - { + } else if (desc) { wchar_t *func; - if (argc-w.woptind != 1) - { - streams.err.append_format(_(L"%ls: Expected exactly one function name\n"), - argv[0]); + if (argc - w.woptind != 1) { + streams.err.append_format(_(L"%ls: Expected exactly one function name\n"), argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } func = argv[w.woptind]; - if (!function_exists(func)) - { - streams.err.append_format(_(L"%ls: Function '%ls' does not exist\n"), - argv[0], - func); + if (!function_exists(func)) { + streams.err.append_format(_(L"%ls: Function '%ls' does not exist\n"), argv[0], func); builtin_print_help(parser, streams, argv[0], streams.err); @@ -1541,98 +1107,78 @@ static int builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t ** function_set_desc(func, desc); return STATUS_BUILTIN_OK; - } - else if (list || (argc==w.woptind)) - { + } else if (list || (argc == w.woptind)) { int is_screen = !streams.out_is_redirected && isatty(STDOUT_FILENO); size_t i; wcstring_list_t names = function_get_names(show_hidden); std::sort(names.begin(), names.end()); - if (is_screen) - { + if (is_screen) { wcstring buff; - for (i=0; i<names.size(); i++) - { + for (i = 0; i < names.size(); i++) { buff.append(names.at(i)); buff.append(L", "); } streams.out.append(reformat_for_screen(buff)); - } - else - { - for (i=0; i<names.size(); i++) - { + } else { + for (i = 0; i < names.size(); i++) { streams.out.append(names.at(i).c_str()); streams.out.append(L"\n"); } } return STATUS_BUILTIN_OK; - } - else if (copy) - { + } else if (copy) { wcstring current_func; wcstring new_func; - if (argc-w.woptind != 2) - { - streams.err.append_format(_(L"%ls: Expected exactly two names (current function name, and new function name)\n"), - argv[0]); + if (argc - w.woptind != 2) { + streams.err.append_format(_(L"%ls: Expected exactly two names (current function name, " + L"and new function name)\n"), + argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } current_func = argv[w.woptind]; - new_func = argv[w.woptind+1]; + new_func = argv[w.woptind + 1]; - if (!function_exists(current_func)) - { - streams.err.append_format(_(L"%ls: Function '%ls' does not exist\n"), - argv[0], - current_func.c_str()); + if (!function_exists(current_func)) { + streams.err.append_format(_(L"%ls: Function '%ls' does not exist\n"), argv[0], + current_func.c_str()); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - if ((wcsfuncname(new_func) != 0) || parser_keywords_is_reserved(new_func)) - { - streams.err.append_format(_(L"%ls: Illegal function name '%ls'\n"), - argv[0], - new_func.c_str()); + if ((wcsfuncname(new_func) != 0) || parser_keywords_is_reserved(new_func)) { + streams.err.append_format(_(L"%ls: Illegal function name '%ls'\n"), argv[0], + new_func.c_str()); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - // keep things simple: don't allow existing names to be copy targets. - if (function_exists(new_func)) - { - streams.err.append_format(_(L"%ls: Function '%ls' already exists. Cannot create copy '%ls'\n"), - argv[0], - new_func.c_str(), - current_func.c_str()); + // Keep things simple: don't allow existing names to be copy targets. + if (function_exists(new_func)) { + streams.err.append_format( + _(L"%ls: Function '%ls' already exists. Cannot create copy '%ls'\n"), argv[0], + new_func.c_str(), current_func.c_str()); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - if (function_copy(current_func, new_func)) - return STATUS_BUILTIN_OK; + if (function_copy(current_func, new_func)) return STATUS_BUILTIN_OK; return STATUS_BUILTIN_ERROR; } - for (i=w.woptind; i<argc; i++) - { + for (i = w.woptind; i < argc; i++) { if (!function_exists(argv[i])) res++; - else - { - if (!query) - { - if (i != w.woptind) - streams.out.append(L"\n"); + else { + if (!query) { + if (i != w.woptind) streams.out.append(L"\n"); streams.out.append(functions_def(argv[i])); } @@ -1642,83 +1188,90 @@ static int builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t ** return res; } -static unsigned int builtin_echo_digit(wchar_t wc, unsigned int base) -{ - // base must be hex or octal - assert(base == 8 || base == 16); - switch (wc) - { - case L'0': +static unsigned int builtin_echo_digit(wchar_t wc, unsigned int base) { + assert(base == 8 || base == 16); // base must be hex or octal + switch (wc) { + case L'0': { return 0; - case L'1': + } + case L'1': { return 1; - case L'2': + } + case L'2': { return 2; - case L'3': + } + case L'3': { return 3; - case L'4': + } + case L'4': { return 4; - case L'5': + } + case L'5': { return 5; - case L'6': + } + case L'6': { return 6; - case L'7': + } + case L'7': { return 7; + } } - if (base == 16) switch (wc) - { - case L'8': + if (base == 16) switch (wc) { + case L'8': { return 8; - case L'9': + } + case L'9': { return 9; + } case L'a': - case L'A': + case L'A': { return 10; + } case L'b': - case L'B': + case L'B': { return 11; + } case L'c': - case L'C': + case L'C': { return 12; + } case L'd': - case L'D': + case L'D': { return 13; + } case L'e': - case L'E': + case L'E': { return 14; + } case L'f': - case L'F': + case L'F': { return 15; + } } return UINT_MAX; } -/* Parse a numeric escape sequence in str, returning whether we succeeded. - Also return the number of characters consumed and the resulting value. - Supported escape sequences: - - \0nnn: octal value, zero to three digits - \nnn: octal value, one to three digits - \xhh: hex value, one to two digits -*/ -static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *consumed, unsigned char *out_val) -{ +/// Parse a numeric escape sequence in str, returning whether we succeeded. Also return the number +/// of characters consumed and the resulting value. Supported escape sequences: +/// +/// \0nnn: octal value, zero to three digits +/// \nnn: octal value, one to three digits +/// \xhh: hex value, one to two digits +static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *consumed, + unsigned char *out_val) { bool success = false; - unsigned int start = 0; //the first character of the numeric part of the sequence + unsigned int start = 0; // the first character of the numeric part of the sequence unsigned int base = 0, max_digits = 0; - if (builtin_echo_digit(str[0], 8) != UINT_MAX) - { + if (builtin_echo_digit(str[0], 8) != UINT_MAX) { // Octal escape base = 8; - // If the first digit is a 0, we allow four digits (including that zero) - // Otherwise we allow 3. + // If the first digit is a 0, we allow four digits (including that zero); otherwise, we + // allow 3. max_digits = (str[0] == L'0' ? 4 : 3); - } - else if (str[0] == L'x') - { + } else if (str[0] == L'x') { // Hex escape base = 16; max_digits = 2; @@ -1727,20 +1280,17 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons start = 1; } - if (base != 0) - { + if (base != 0) { unsigned int idx; - unsigned char val = 0; //resulting character - for (idx = start; idx < start + max_digits; idx++) - { + unsigned char val = 0; // resulting character + for (idx = start; idx < start + max_digits; idx++) { unsigned int digit = builtin_echo_digit(str[idx], base); if (digit == UINT_MAX) break; val = val * base + digit; } - // We succeeded if we consumed at least one digit - if (idx > start) - { + // We succeeded if we consumed at least one digit. + if (idx > start) { *consumed = idx; *out_val = val; success = true; @@ -1749,140 +1299,137 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons return success; } -/** The echo builtin. - bash only respects -n if it's the first argument. We'll do the same. - We also support a new option -s to mean "no spaces" -*/ - -static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The echo builtin. +/// +/// Bash only respects -n if it's the first argument. We'll do the same. We also support a new +/// option -s to mean "no spaces" +static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) { /* Skip first arg */ - if (! *argv++) - return STATUS_BUILTIN_ERROR; + if (!*argv++) return STATUS_BUILTIN_ERROR; - /* Process options. Options must come at the beginning - the first non-option kicks us out. */ + // Process options. Options must come at the beginning - the first non-option kicks us out. bool print_newline = true, print_spaces = true, interpret_special_chars = false; size_t option_idx = 0; - for (option_idx = 0; argv[option_idx] != NULL; option_idx++) - { + for (option_idx = 0; argv[option_idx] != NULL; option_idx++) { const wchar_t *arg = argv[option_idx]; assert(arg != NULL); bool arg_is_valid_option = false; - if (arg[0] == L'-') - { + if (arg[0] == L'-') { // We have a leading dash. Ensure that every subseqnent character is a valid option. size_t i = 1; - while (arg[i] != L'\0' && wcschr(L"nesE", arg[i]) != NULL) - { + while (arg[i] != L'\0' && wcschr(L"nesE", arg[i]) != NULL) { i++; } - // We must have at least two characters to be a valid option, and have consumed the whole string + // We must have at least two characters to be a valid option, and have consumed the + // whole string. arg_is_valid_option = (i >= 2 && arg[i] == L'\0'); } - - if (! arg_is_valid_option) - { - // This argument is not an option, so there are no more options + + if (!arg_is_valid_option) { + // This argument is not an option, so there are no more options. break; } - + // Ok, we are sure the argument is an option. Parse it. assert(arg_is_valid_option); - for (size_t i=1; arg[i] != L'\0'; i++) - { - switch (arg[i]) - { - case L'n': + for (size_t i = 1; arg[i] != L'\0'; i++) { + switch (arg[i]) { + case L'n': { print_newline = false; break; - case L'e': + } + case L'e': { interpret_special_chars = true; break; - case L's': + } + case L's': { print_spaces = false; break; - case L'E': + } + case L'E': { interpret_special_chars = false; break; - default: + } + default: { assert(0 && "Unexpected character in builtin_echo argument"); break; + } } } } - /* The special character \c can be used to indicate no more output */ + // The special character \c can be used to indicate no more output. bool continue_output = true; - + /* Skip over the options */ - const wchar_t * const *args_to_echo = argv + option_idx; - for (size_t idx = 0; continue_output && args_to_echo[idx] != NULL; idx++) - { - if (print_spaces && idx > 0) - { + const wchar_t *const *args_to_echo = argv + option_idx; + for (size_t idx = 0; continue_output && args_to_echo[idx] != NULL; idx++) { + if (print_spaces && idx > 0) { streams.out.push_back(' '); } const wchar_t *str = args_to_echo[idx]; - for (size_t j=0; continue_output && str[j]; j++) - { - if (! interpret_special_chars || str[j] != L'\\') - { - /* Not an escape */ + for (size_t j = 0; continue_output && str[j]; j++) { + if (!interpret_special_chars || str[j] != L'\\') { + // Not an escape. streams.out.push_back(str[j]); - } - else - { - /* Most escapes consume one character in addition to the backslash; the numeric sequences may consume more, while an unrecognized escape sequence consumes none. */ + } else { + // Most escapes consume one character in addition to the backslash; the numeric + // sequences may consume more, while an unrecognized escape sequence consumes none. wchar_t wc; size_t consumed = 1; - switch (str[j+1]) - { - case L'a': + switch (str[j + 1]) { + case L'a': { wc = L'\a'; break; - case L'b': + } + case L'b': { wc = L'\b'; break; - case L'e': + } + case L'e': { wc = L'\x1B'; break; - case L'f': + } + case L'f': { wc = L'\f'; break; - case L'n': + } + case L'n': { wc = L'\n'; break; - case L'r': + } + case L'r': { wc = L'\r'; break; - case L't': + } + case L't': { wc = L'\t'; break; - case L'v': + } + case L'v': { wc = L'\v'; break; - case L'\\': + } + case L'\\': { wc = L'\\'; break; - - case L'c': + } + case L'c': { wc = 0; continue_output = false; break; - - default: - { - /* Octal and hex escape sequences */ + } + default: { + // Octal and hex escape sequences. unsigned char narrow_val = 0; - if (builtin_echo_parse_numeric_sequence(str + j + 1, &consumed, &narrow_val)) - { - /* Here consumed must have been set to something. The narrow_val is a literal byte that we want to output (#1894) */ + if (builtin_echo_parse_numeric_sequence(str + j + 1, &consumed, + &narrow_val)) { + // Here consumed must have been set to something. The narrow_val is a + // literal byte that we want to output (#1894). wc = ENCODE_DIRECT_BASE + narrow_val % 256; - } - else - { - /* Not a recognized escape. We consume only the backslash. */ + } else { + // Not a recognized escape. We consume only the backslash. wc = L'\\'; consumed = 0; } @@ -1890,258 +1437,201 @@ static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) } } - /* Skip over characters that were part of this escape sequence (but not the backslash, which will be handled by the loop increment */ + // Skip over characters that were part of this escape sequence (but not the + // backslash, which will be handled by the loop increment. j += consumed; - if (continue_output) - { + if (continue_output) { streams.out.push_back(wc); } } } } - if (print_newline && continue_output) - { + if (print_newline && continue_output) { streams.out.push_back('\n'); } return STATUS_BUILTIN_OK; } -// The pwd builtin. We don't respect -P to resolve symbolic links because we -// try to always resolve them. -static int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The pwd builtin. We don't respect -P to resolve symbolic links because we +/// try to always resolve them. +static int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wcstring res = wgetcwd(); - if (res.empty()) - { + if (res.empty()) { return STATUS_BUILTIN_ERROR; } - else - { - streams.out.append(res); - streams.out.push_back(L'\n'); - return STATUS_BUILTIN_OK; - } + streams.out.append(res); + streams.out.push_back(L'\n'); + return STATUS_BUILTIN_OK; } -/** Adds a function to the function set. It calls into function.cpp to perform any heavy lifting. */ -int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, const wcstring &contents, int definition_line_offset, wcstring *out_err) -{ +/// Adds a function to the function set. It calls into function.cpp to perform any heavy lifting. +int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, + const wcstring &contents, int definition_line_offset, wcstring *out_err) { wgetopter_t w; assert(out_err != NULL); - /* wgetopt expects 'function' as the first argument. Make a new wcstring_list with that property. */ + // wgetopt expects 'function' as the first argument. Make a new wcstring_list with that + // property. wcstring_list_t args; args.push_back(L"function"); args.insert(args.end(), c_args.begin(), c_args.end()); - /* Hackish const_cast matches the one in builtin_run */ + // Hackish const_cast matches the one in builtin_run. const null_terminated_array_t<wchar_t> argv_array(args); wchar_t **argv = const_cast<wchar_t **>(argv_array.get()); int argc = builtin_count_args(argv); - int res=STATUS_BUILTIN_OK; - wchar_t *desc=0; + int res = STATUS_BUILTIN_OK; + wchar_t *desc = 0; std::vector<event_t> events; - + bool has_named_arguments = false; wcstring_list_t named_arguments; wcstring_list_t inherit_vars; - bool shadows = true; + bool shadow_builtin = false; + bool shadow_scope = true; wcstring_list_t wrap_targets; - - /* If -a/--argument-names is specified before the function name, - then the function name is the last positional, e.g. `function -a arg1 arg2 name`. - If it is specified after the function name (or not specified at all) then the - function name is the first positional. This is the common case. */ + + // If -a/--argument-names is specified before the function name, then the function name is the + // last positional, e.g. `function -a arg1 arg2 name`. If it is specified after the function + // name (or not specified at all) then the function name is the first positional. This is the + // common case. bool name_is_first_positional = true; wcstring_list_t positionals; - - const struct woption long_options[] = - { - { L"description", required_argument, 0, 'd' }, - { L"on-signal", required_argument, 0, 's' }, - { L"on-job-exit", required_argument, 0, 'j' }, - { L"on-process-exit", required_argument, 0, 'p' }, - { L"on-variable", required_argument, 0, 'v' }, - { L"on-event", required_argument, 0, 'e' }, - { L"wraps", required_argument, 0, 'w' }, - { L"help", no_argument, 0, 'h' }, - { L"argument-names", no_argument, 0, 'a' }, - { L"no-scope-shadowing", no_argument, 0, 'S' }, - { L"inherit-variable", required_argument, 0, 'V' }, - { 0, 0, 0, 0 } - }; - while (1 && (!res)) - { + const struct woption long_options[] = {{L"description", required_argument, 0, 'd'}, + {L"on-signal", required_argument, 0, 's'}, + {L"on-job-exit", required_argument, 0, 'j'}, + {L"on-process-exit", required_argument, 0, 'p'}, + {L"on-variable", required_argument, 0, 'v'}, + {L"on-event", required_argument, 0, 'e'}, + {L"wraps", required_argument, 0, 'w'}, + {L"help", no_argument, 0, 'h'}, + {L"argument-names", no_argument, 0, 'a'}, + {L"shadow-builtin", no_argument, 0, 'B'}, + {L"no-scope-shadowing", no_argument, 0, 'S'}, + {L"inherit-variable", required_argument, 0, 'V'}, + {0, 0, 0, 0}}; + + while (1 && !res) { int opt_index = 0; - // The leading - here specifies RETURN_IN_ORDER - int opt = w.wgetopt_long(argc, - argv, - L"-d:s:j:p:v:e:w:haSV:", - long_options, - &opt_index); - if (opt == -1) - break; - - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - - - - append_format(*out_err, - BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); - + // The leading - here specifies RETURN_IN_ORDER. + int opt = w.wgetopt_long(argc, argv, L"-d:s:j:p:v:e:w:haBSV:", long_options, &opt_index); + if (opt == -1) break; + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + append_format(*out_err, BUILTIN_ERR_UNKNOWN, argv[0], long_options[opt_index].name); res = 1; break; - - case 'd': - desc=w.woptarg; + } + case 'd': { + desc = w.woptarg; break; - - case 's': - { + } + case 's': { int sig = wcs2sig(w.woptarg); - - if (sig < 0) - { - append_format(*out_err, - _(L"%ls: Unknown signal '%ls'"), - argv[0], - w.woptarg); - res=1; + if (sig < 0) { + append_format(*out_err, _(L"%ls: Unknown signal '%ls'"), argv[0], w.woptarg); + res = 1; break; } events.push_back(event_t::signal_event(sig)); break; } - - case 'v': - { - if (wcsvarname(w.woptarg)) - { - append_format(*out_err, - _(L"%ls: Invalid variable name '%ls'"), - argv[0], + case 'v': { + if (wcsvarname(w.woptarg)) { + append_format(*out_err, _(L"%ls: Invalid variable name '%ls'"), argv[0], w.woptarg); - res=STATUS_BUILTIN_ERROR; + res = STATUS_BUILTIN_ERROR; break; } events.push_back(event_t::variable_event(w.woptarg)); break; } - - - case 'e': - { + case 'e': { events.push_back(event_t::generic_event(w.woptarg)); break; } - case 'j': - case 'p': - { + case 'p': { pid_t pid; wchar_t *end; event_t e(EVENT_ANY); - if ((opt == 'j') && - (wcscasecmp(w.woptarg, L"caller") == 0)) - { + if ((opt == 'j') && (wcscasecmp(w.woptarg, L"caller") == 0)) { int job_id = -1; - if (is_subshell) - { + if (is_subshell) { size_t block_idx = 0; - /* Find the outermost substitution block */ - for (block_idx = 0; ; block_idx++) - { + // Find the outermost substitution block. + for (block_idx = 0;; block_idx++) { const block_t *b = parser.block_at_index(block_idx); - if (b == NULL || b->type() == SUBST) - break; + if (b == NULL || b->type() == SUBST) break; } - /* Go one step beyond that, to get to the caller */ + // Go one step beyond that, to get to the caller. const block_t *caller_block = parser.block_at_index(block_idx + 1); - if (caller_block != NULL && caller_block->job != NULL) - { + if (caller_block != NULL && caller_block->job != NULL) { job_id = caller_block->job->job_id; } } - if (job_id == -1) - { + if (job_id == -1) { append_format(*out_err, _(L"%ls: Cannot find calling job for event handler"), argv[0]); - res=1; - } - else - { + res = 1; + } else { e.type = EVENT_JOB_ID; e.param1.job_id = job_id; } - - } - else - { + } else { errno = 0; pid = fish_wcstoi(w.woptarg, &end, 10); - if (errno || !end || *end) - { - append_format(*out_err, - _(L"%ls: Invalid process id %ls"), - argv[0], + if (errno || !end || *end) { + append_format(*out_err, _(L"%ls: Invalid process id %ls"), argv[0], w.woptarg); - res=1; + res = 1; break; } - e.type = EVENT_EXIT; - e.param1.pid = (opt=='j'?-1:1)*abs(pid); - } - if (res) - { - /* nothing */ + e.param1.pid = (opt == 'j' ? -1 : 1) * abs(pid); } - else - { + if (!res) { events.push_back(e); } break; } - - case 'a': + case 'a': { has_named_arguments = true; - /* The function name is the first positional unless -a comes before all positionals */ - name_is_first_positional = ! positionals.empty(); + // The function name is the first positional unless -a comes before all positionals. + name_is_first_positional = !positionals.empty(); break; - - case 'S': - shadows = 0; + } + case 'B': { + shadow_builtin = true; break; - - case 'w': + } + case 'S': { + shadow_scope = false; + break; + } + case 'w': { wrap_targets.push_back(w.woptarg); break; - - case 'V': - { - if (wcsvarname(w.woptarg)) - { - append_format(*out_err, _(L"%ls: Invalid variable name '%ls'"), argv[0], w.woptarg); + } + case 'V': { + if (wcsvarname(w.woptarg)) { + append_format(*out_err, _(L"%ls: Invalid variable name '%ls'"), argv[0], + w.woptarg); res = STATUS_BUILTIN_ERROR; break; } @@ -2149,120 +1639,112 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list inherit_vars.push_back(w.woptarg); break; } - - case 'h': + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case 1: + } + case 1: { assert(w.woptarg != NULL); positionals.push_back(w.woptarg); break; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); res = 1; break; - + } } - } - if (!res) - { - /* Determine the function name, and remove it from the list of positionals */ + if (!res) { + // Determine the function name, and remove it from the list of positionals. wcstring function_name; bool name_is_missing = positionals.empty(); - if (! name_is_missing) - { - if (name_is_first_positional) - { + if (!name_is_missing) { + if (name_is_first_positional) { function_name = positionals.front(); positionals.erase(positionals.begin()); - } - else - { + } else { function_name = positionals.back(); positionals.erase(positionals.end() - 1); } } - - if (name_is_missing) - { - append_format(*out_err, - _(L"%ls: Expected function name"), - argv[0]); - res=1; - } - else if (wcsfuncname(function_name)) - { - append_format(*out_err, - _(L"%ls: Illegal function name '%ls'"), - argv[0], - function_name.c_str()); - res=1; - } - else if (parser_keywords_is_reserved(function_name)) - { - - append_format(*out_err, - _(L"%ls: The name '%ls' is reserved,\nand can not be used as a function name"), - argv[0], + if (name_is_missing) { + append_format(*out_err, _(L"%ls: Expected function name"), argv[0]); + res = 1; + } else if (wcsfuncname(function_name)) { + append_format(*out_err, _(L"%ls: Illegal function name '%ls'"), argv[0], function_name.c_str()); - res=1; - } - else if (function_name.empty()) - { + res = 1; + } else if (parser_keywords_is_reserved(function_name)) { + append_format( + *out_err, + _(L"%ls: The name '%ls' is reserved,\nand can not be used as a function name"), + argv[0], function_name.c_str()); + + res = 1; + } else if (function_name.empty()) { append_format(*out_err, _(L"%ls: No function name given"), argv[0]); - res=1; - } - else - { - if (has_named_arguments) - { - /* All remaining positionals are named arguments */ + res = 1; + } else { + if (has_named_arguments) { + // All remaining positionals are named arguments. named_arguments.swap(positionals); - for (size_t i=0; i < named_arguments.size(); i++) - { - if (wcsvarname(named_arguments.at(i))) - { - append_format(*out_err, - _(L"%ls: Invalid variable name '%ls'"), - argv[0], + for (size_t i = 0; i < named_arguments.size(); i++) { + if (wcsvarname(named_arguments.at(i))) { + append_format(*out_err, _(L"%ls: Invalid variable name '%ls'"), argv[0], named_arguments.at(i).c_str()); res = STATUS_BUILTIN_ERROR; break; } } - } - else if (! positionals.empty()) - { - // +1 because we already got the function name - append_format(*out_err, - _(L"%ls: Expected one argument, got %lu"), - argv[0], + } else if (!positionals.empty()) { + // +1 because we already got the function name. + append_format(*out_err, _(L"%ls: Expected one argument, got %lu"), argv[0], (unsigned long)(positionals.size() + 1)); - res=1; + res = 1; } } - if (!res) - { - /* Here we actually define the function! */ + if (!res) { + bool function_name_shadows_builtin = false; + wcstring_list_t builtin_names = builtin_get_names(); + for (size_t i = 0; i < builtin_names.size(); i++) { + const wchar_t *el = builtin_names.at(i).c_str(); + if (el == function_name) { + function_name_shadows_builtin = true; + break; + } + } + if (function_name_shadows_builtin && !shadow_builtin) { + append_format( + *out_err, + _(L"%ls: function name shadows a builtin so you must use '--shadow-builtin'"), + argv[0]); + res = STATUS_BUILTIN_ERROR; + } else if (!function_name_shadows_builtin && shadow_builtin) { + append_format(*out_err, _(L"%ls: function name does not shadow a builtin so you " + L"must not use '--shadow-builtin'"), + argv[0]); + res = STATUS_BUILTIN_ERROR; + } + } + + if (!res) { + // Here we actually define the function! function_data_t d; d.name = function_name; - if (desc) - d.description = desc; + if (desc) d.description = desc; d.events.swap(events); - d.shadows = shadows; + d.shadow_builtin = shadow_builtin; + d.shadow_scope = shadow_scope; d.named_arguments.swap(named_arguments); d.inherit_vars.swap(inherit_vars); - for (size_t i=0; i<d.events.size(); i++) - { + for (size_t i = 0; i < d.events.size(); i++) { event_t &e = d.events.at(i); e.function_name = d.name; } @@ -2271,9 +1753,8 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list function_add(d, parser, definition_line_offset); - // Handle wrap targets - for (size_t w=0; w < wrap_targets.size(); w++) - { + // Handle wrap targets. + for (size_t w = 0; w < wrap_targets.size(); w++) { complete_add_wrapper(function_name, wrap_targets.at(w)); } } @@ -2282,76 +1763,47 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list return res; } -/** - The random builtin. For generating random numbers. -*/ -static int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ - static int seeded=0; +// The random builtin. For generating random numbers. +static int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) { + static int seeded = 0; static struct drand48_data seed_buffer; int argc = builtin_count_args(argv); wgetopter_t w; - static const struct woption - long_options[] = - { - { - L"help", no_argument, 0, 'h' - } - , - { - 0, 0, 0, 0 - } - } - ; + static const struct woption long_options[] = {{L"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"h", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"h", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); - return STATUS_BUILTIN_ERROR; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); break; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } - switch (argc-w.woptind) - { - case 0: - { + switch (argc - w.woptind) { + case 0: { long res; - - if (!seeded) - { - seeded=1; + if (!seeded) { + seeded = 1; srand48_r(time(0), &seed_buffer); } lrand48_r(&seed_buffer, &res); @@ -2360,32 +1812,25 @@ static int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **arg streams.out.append_format(L"%ld\n", labs(res % 32768)); break; } - - case 1: - { + case 1: { long foo; - wchar_t *end=0; + wchar_t *end = 0; - errno=0; + errno = 0; foo = wcstol(argv[w.woptind], &end, 10); - if (errno || *end) - { + if (errno || *end) { streams.err.append_format(_(L"%ls: Seed value '%ls' is not a valid number\n"), - argv[0], - argv[w.woptind]); + argv[0], argv[w.woptind]); return STATUS_BUILTIN_ERROR; } - seeded=1; + seeded = 1; srand48_r(foo, &seed_buffer); break; } - - default: - { - streams.err.append_format(_(L"%ls: Expected zero or one argument, got %d\n"), - argv[0], - argc-w.woptind); + default: { + streams.err.append_format(_(L"%ls: Expected zero or one argument, got %d\n"), argv[0], + argc - w.woptind); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } @@ -2393,12 +1838,8 @@ static int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **arg return STATUS_BUILTIN_OK; } - -/** - The read builtin. Reads from stdin and stores the values in environment variables. -*/ -static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The read builtin. Reads from stdin and stores the values in environment variables. +static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; wcstring buff; int i, argc = builtin_count_args(argv); @@ -2406,260 +1847,182 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) const wchar_t *prompt = DEFAULT_READ_PROMPT; const wchar_t *right_prompt = L""; const wchar_t *commandline = L""; - int exit_res=STATUS_BUILTIN_OK; + int exit_res = STATUS_BUILTIN_OK; const wchar_t *mode_name = READ_MODE_NAME; - int nchars=0; + int nchars = 0; wchar_t *end; int shell = 0; int array = 0; bool split_null = false; - while (1) - { - static const struct woption - long_options[] = - { - { - L"export", no_argument, 0, 'x' - } - , - { - L"global", no_argument, 0, 'g' - } - , - { - L"local", no_argument, 0, 'l' - } - , - { - L"universal", no_argument, 0, 'U' - } - , - { - L"unexport", no_argument, 0, 'u' - } - , - { - L"prompt", required_argument, 0, 'p' - } - , - { - L"right-prompt", required_argument, 0, 'R' - } - , - { - L"command", required_argument, 0, 'c' - } - , - { - L"mode-name", required_argument, 0, 'm' - } - , - { - L"nchars", required_argument, 0, 'n' - } - , - { - L"shell", no_argument, 0, 's' - } - , - { - L"array", no_argument, 0, 'a' - } - , - { - L"null", no_argument, 0, 'z' - } - , - { - L"help", no_argument, 0, 'h' - } - , - { - 0, 0, 0, 0 - } - } - ; + while (1) { + static const struct woption long_options[] = {{L"export", no_argument, 0, 'x'}, + {L"global", no_argument, 0, 'g'}, + {L"local", no_argument, 0, 'l'}, + {L"universal", no_argument, 0, 'U'}, + {L"unexport", no_argument, 0, 'u'}, + {L"prompt", required_argument, 0, 'p'}, + {L"right-prompt", required_argument, 0, 'R'}, + {L"command", required_argument, 0, 'c'}, + {L"mode-name", required_argument, 0, 'm'}, + {L"nchars", required_argument, 0, 'n'}, + {L"shell", no_argument, 0, 's'}, + {L"array", no_argument, 0, 'a'}, + {L"null", no_argument, 0, 'z'}, + {L"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"xglUup:R:c:hm:n:saz", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"xglUup:R:c:hm:n:saz", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); - return STATUS_BUILTIN_ERROR; - - case L'x': + } + case L'x': { place |= ENV_EXPORT; break; - - case L'g': + } + case L'g': { place |= ENV_GLOBAL; break; - - case L'l': + } + case L'l': { place |= ENV_LOCAL; break; - - case L'U': + } + case L'U': { place |= ENV_UNIVERSAL; break; - - case L'u': + } + case L'u': { place |= ENV_UNEXPORT; break; - - case L'p': + } + case L'p': { prompt = w.woptarg; break; - - case L'R': + } + case L'R': { right_prompt = w.woptarg; break; - - case L'c': + } + case L'c': { commandline = w.woptarg; break; - - case L'm': + } + case L'm': { mode_name = w.woptarg; break; - - case L'n': + } + case L'n': { errno = 0; nchars = fish_wcstoi(w.woptarg, &end, 10); - if (errno || *end != 0) - { - switch (errno) - { - case ERANGE: - streams.err.append_format( _(L"%ls: Argument '%ls' is out of range\n"), - argv[0], - w.woptarg); + if (errno || *end != 0) { + switch (errno) { + case ERANGE: { + streams.err.append_format(_(L"%ls: Argument '%ls' is out of range\n"), + argv[0], w.woptarg); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; - - default: - streams.err.append_format( _(L"%ls: Argument '%ls' must be an integer\n"), - argv[0], - w.woptarg); + } + default: { + streams.err.append_format( + _(L"%ls: Argument '%ls' must be an integer\n"), argv[0], w.woptarg); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; + } } } break; - - case 's': + } + case 's': { shell = 1; break; - - case 'a': + } + case 'a': { array = 1; break; - - case L'z': + } + case L'z': { split_null = true; break; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case L'?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case L'?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; + } } - } - if ((place & ENV_UNEXPORT) && (place & ENV_EXPORT)) - { - streams.err.append_format(BUILTIN_ERR_EXPUNEXP, - argv[0]); - + if ((place & ENV_UNEXPORT) && (place & ENV_EXPORT)) { + streams.err.append_format(BUILTIN_ERR_EXPUNEXP, argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - if ((place&ENV_LOCAL?1:0) + (place & ENV_GLOBAL?1:0) + (place & ENV_UNIVERSAL?1:0) > 1) - { - streams.err.append_format(BUILTIN_ERR_GLOCAL, - argv[0]); + if ((place & ENV_LOCAL ? 1 : 0) + (place & ENV_GLOBAL ? 1 : 0) + + (place & ENV_UNIVERSAL ? 1 : 0) > + 1) { + streams.err.append_format(BUILTIN_ERR_GLOCAL, argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - if (array && w.woptind+1 != argc) - { - streams.err.append_format(_(L"%ls: --array option requires a single variable name.\n"), argv[0]); + if (array && w.woptind + 1 != argc) { + streams.err.append_format(_(L"%ls: --array option requires a single variable name.\n"), + argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - /* - Verify all variable names - */ - for (i=w.woptind; i<argc; i++) - { + // Verify all variable names. + for (i = w.woptind; i < argc; i++) { wchar_t *src; - if (!wcslen(argv[i])) - { + if (!wcslen(argv[i])) { streams.err.append_format(BUILTIN_ERR_VARNAME_ZERO, argv[0]); return STATUS_BUILTIN_ERROR; } - for (src=argv[i]; *src; src++) - { - if ((!iswalnum(*src)) && (*src != L'_')) - { + for (src = argv[i]; *src; src++) { + if ((!iswalnum(*src)) && (*src != L'_')) { streams.err.append_format(BUILTIN_ERR_VARCHAR, argv[0], *src); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } } - } - /* - The call to reader_readline may change woptind, so we save it away here - */ - i=w.woptind; + // The call to reader_readline may change woptind, so we save it away here. + i = w.woptind; - /* - Check if we should read interactively using \c reader_readline() - */ - if (isatty(0) && streams.stdin_fd == STDIN_FILENO && !split_null) - { + // Check if we should read interactively using \c reader_readline(). + if (isatty(0) && streams.stdin_fd == STDIN_FILENO && !split_null) { const wchar_t *line; reader_push(mode_name); reader_set_left_prompt(prompt); reader_set_right_prompt(right_prompt); - if (shell) - { + if (shell) { reader_set_complete_function(&complete); reader_set_highlight_function(&highlight_shell); reader_set_test_function(&reader_shell_test); } - /* No autosuggestions or abbreviations in builtin_read */ + // No autosuggestions or abbreviations in builtin_read. reader_set_allow_autosuggesting(false); reader_set_expand_abbreviations(false); reader_set_exit_on_interrupt(true); @@ -2670,177 +2033,139 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) event_fire_generic(L"fish_prompt"); line = reader_readline(nchars); proc_pop_interactive(); - if (line) - { - if (0 < nchars && nchars < wcslen(line)) - { - // line may be longer than nchars if a keybinding used `commandline -i` + if (line) { + if (0 < nchars && nchars < wcslen(line)) { + // Line may be longer than nchars if a keybinding used `commandline -i` // note: we're deliberately throwing away the tail of the commandline. // It shouldn't be unread because it was produced with `commandline -i`, // not typed. buff = wcstring(line, nchars); - } - else - { + } else { buff = wcstring(line); } - } - else - { + } else { exit_res = STATUS_BUILTIN_ERROR; } reader_pop(); - } - else - { - int eof=0; + } else { + int eof = 0; buff.clear(); - while (1) - { + while (1) { int finished = 0; wchar_t res = 0; mbstate_t state = {}; - while (!finished) - { + while (!finished) { char b; - if (read_blocked(streams.stdin_fd, &b, 1) <= 0) - { - eof=1; + if (read_blocked(streams.stdin_fd, &b, 1) <= 0) { + eof = 1; break; } - if (MB_CUR_MAX == 1) // single-byte locale + if (MB_CUR_MAX == 1) // single-byte locale { res = (unsigned char)b; finished = 1; - } - else { + } else { size_t sz = mbrtowc(&res, &b, 1, &state); - switch (sz) - { - case (size_t)-1: + switch (sz) { + case (size_t)-1: { memset(&state, 0, sizeof(state)); break; - - case (size_t)-2: + } + case (size_t)-2: { break; - - default: + } + default: { finished = 1; break; + } } } } - if (eof) - break; + if (eof) break; - if (!split_null && res == L'\n') - break; + if (!split_null && res == L'\n') break; - if (split_null && res == L'\0') - break; + if (split_null && res == L'\0') break; buff.push_back(res); - if (0 < nchars && (size_t)nchars <= buff.size()) - { + if (0 < nchars && (size_t)nchars <= buff.size()) { break; } } - if (buff.empty() && eof) - { + if (buff.empty() && eof) { exit_res = 1; } } - if (i != argc && !exit_res) - { + if (i != argc && !exit_res) { env_var_t ifs = env_get_string(L"IFS"); - if (ifs.missing_or_empty()) - { - /* Every character is a separate token */ + if (ifs.missing_or_empty()) { + // Every character is a separate token. size_t bufflen = buff.size(); - if (array) - { - if (bufflen > 0) - { - wcstring chars(bufflen+(bufflen-1), ARRAY_SEP); + if (array) { + if (bufflen > 0) { + wcstring chars(bufflen + (bufflen - 1), ARRAY_SEP); wcstring::iterator out = chars.begin(); - for (wcstring::const_iterator it = buff.begin(), end = buff.end(); it != end; ++it) - { + for (wcstring::const_iterator it = buff.begin(), end = buff.end(); it != end; + ++it) { *out = *it; out += 2; } env_set(argv[i], chars.c_str(), place); - } - else - { + } else { env_set(argv[i], NULL, place); } - } - else - { + } else { size_t j = 0; - for (; i+1 < argc; ++i) - { - if (j < bufflen) - { + for (; i + 1 < argc; ++i) { + if (j < bufflen) { wchar_t buffer[2] = {buff[j++], 0}; env_set(argv[i], buffer, place); - } - else - { + } else { env_set(argv[i], L"", place); } } if (i < argc) env_set(argv[i], &buff[j], place); } - } - else if (array) - { + } else if (array) { wcstring tokens; tokens.reserve(buff.size()); bool empty = true; - - for (wcstring_range loc = wcstring_tok(buff, ifs); loc.first != wcstring::npos; loc = wcstring_tok(buff, ifs, loc)) - { + + for (wcstring_range loc = wcstring_tok(buff, ifs); loc.first != wcstring::npos; + loc = wcstring_tok(buff, ifs, loc)) { if (!empty) tokens.push_back(ARRAY_SEP); tokens.append(buff, loc.first, loc.second); empty = false; } env_set(argv[i], empty ? NULL : tokens.c_str(), place); - } - else - { - wcstring_range loc = wcstring_range(0,0); + } else { + wcstring_range loc = wcstring_range(0, 0); - while (i<argc) - { - loc = wcstring_tok(buff, (i+1<argc) ? ifs : wcstring(), loc); - env_set(argv[i], loc.first == wcstring::npos ? L"" : &buff.c_str()[loc.first], place); + while (i < argc) { + loc = wcstring_tok(buff, (i + 1 < argc) ? ifs : wcstring(), loc); + env_set(argv[i], loc.first == wcstring::npos ? L"" : &buff.c_str()[loc.first], + place); ++i; } - } } return exit_res; } -/** - The status builtin. Gives various status information on fish. -*/ -static int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The status builtin. Gives various status information on fish. +static int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; - enum - { + enum { NORMAL, IS_SUBST, IS_BLOCK, @@ -2853,216 +2178,151 @@ static int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **arg DONE, CURRENT_FILENAME, CURRENT_LINE_NUMBER - } - ; + }; int mode = NORMAL; int argc = builtin_count_args(argv); - int res=STATUS_BUILTIN_OK; - - - const struct woption - long_options[] = - { - { - L"help", no_argument, 0, 'h' - } - , - { - L"is-command-substitution", no_argument, 0, 'c' - } - , - { - L"is-block", no_argument, 0, 'b' - } - , - { - L"is-interactive", no_argument, 0, 'i' - } - , - { - L"is-login", no_argument, 0, 'l' - } - , - { - L"is-full-job-control", no_argument, &mode, IS_FULL_JOB_CONTROL - } - , - { - L"is-interactive-job-control", no_argument, &mode, IS_INTERACTIVE_JOB_CONTROL - } - , - { - L"is-no-job-control", no_argument, &mode, IS_NO_JOB_CONTROL - } - , - { - L"current-filename", no_argument, 0, 'f' - } - , - { - L"current-line-number", no_argument, 0, 'n' - } - , - { - L"job-control", required_argument, 0, 'j' - } - , - { - L"print-stack-trace", no_argument, 0, 't' - } - , - { - 0, 0, 0, 0 - } - } - ; + int res = STATUS_BUILTIN_OK; - while (1) - { + const struct woption long_options[] = { + {L"help", no_argument, 0, 'h'}, + {L"is-command-substitution", no_argument, 0, 'c'}, + {L"is-block", no_argument, 0, 'b'}, + {L"is-interactive", no_argument, 0, 'i'}, + {L"is-login", no_argument, 0, 'l'}, + {L"is-full-job-control", no_argument, &mode, IS_FULL_JOB_CONTROL}, + {L"is-interactive-job-control", no_argument, &mode, IS_INTERACTIVE_JOB_CONTROL}, + {L"is-no-job-control", no_argument, &mode, IS_NO_JOB_CONTROL}, + {L"current-filename", no_argument, 0, 'f'}, + {L"current-line-number", no_argument, 0, 'n'}, + {L"job-control", required_argument, 0, 'j'}, + {L"print-stack-trace", no_argument, 0, 't'}, + {0, 0, 0, 0}}; + + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L":cbilfnhj:t", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L":cbilfnhj:t", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; - - case 'c': + } + case 'c': { mode = IS_SUBST; break; - - case 'b': + } + case 'b': { mode = IS_BLOCK; break; - - case 'i': + } + case 'i': { mode = IS_INTERACTIVE; break; - - case 'l': + } + case 'l': { mode = IS_LOGIN; break; - - case 'f': + } + case 'f': { mode = CURRENT_FILENAME; break; - - case 'n': + } + case 'n': { mode = CURRENT_LINE_NUMBER; break; - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - case 'j': + } + case 'j': { if (wcscmp(w.woptarg, L"full") == 0) job_control_mode = JOB_CONTROL_ALL; else if (wcscmp(w.woptarg, L"interactive") == 0) job_control_mode = JOB_CONTROL_INTERACTIVE; else if (wcscmp(w.woptarg, L"none") == 0) job_control_mode = JOB_CONTROL_NONE; - else - { - streams.err.append_format(L"%ls: Invalid job control mode '%ls'\n", - L"status", w.woptarg); + else { + streams.err.append_format(L"%ls: Invalid job control mode '%ls'\n", L"status", + w.woptarg); res = 1; } mode = DONE; break; - - case 't': + } + case 't': { mode = STACK_TRACE; break; - - - case ':': - builtin_missing_argument(parser, streams, argv[0], argv[w.woptind-1]); + } + case ':': { + builtin_missing_argument(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - + } } - } - if (!res) - { - - switch (mode) - { - case CURRENT_FILENAME: - { + if (!res) { + switch (mode) { + case CURRENT_FILENAME: { const wchar_t *fn = parser.current_filename(); - if (!fn) - fn = _(L"Standard input"); + if (!fn) fn = _(L"Standard input"); - streams.out.append_format( L"%ls\n", fn); + streams.out.append_format(L"%ls\n", fn); break; } - - case CURRENT_LINE_NUMBER: - { - streams.out.append_format( L"%d\n", parser.get_lineno()); + case CURRENT_LINE_NUMBER: { + streams.out.append_format(L"%d\n", parser.get_lineno()); break; } - - case IS_INTERACTIVE: + case IS_INTERACTIVE: { return !is_interactive_session; - - case IS_SUBST: + } + case IS_SUBST: { return !is_subshell; - - case IS_BLOCK: + } + case IS_BLOCK: { return !is_block; - - case IS_LOGIN: + } + case IS_LOGIN: { return !is_login; - - case IS_FULL_JOB_CONTROL: + } + case IS_FULL_JOB_CONTROL: { return job_control_mode != JOB_CONTROL_ALL; - - case IS_INTERACTIVE_JOB_CONTROL: + } + case IS_INTERACTIVE_JOB_CONTROL: { return job_control_mode != JOB_CONTROL_INTERACTIVE; - - case IS_NO_JOB_CONTROL: + } + case IS_NO_JOB_CONTROL: { return job_control_mode != JOB_CONTROL_NONE; - - case STACK_TRACE: - { + } + case STACK_TRACE: { streams.out.append(parser.stack_trace()); break; } - - case NORMAL: - { + case NORMAL: { if (is_login) - streams.out.append_format( _(L"This is a login shell\n")); + streams.out.append_format(_(L"This is a login shell\n")); else - streams.out.append_format( _(L"This is not a login shell\n")); + streams.out.append_format(_(L"This is not a login shell\n")); - streams.out.append_format( _(L"Job control: %ls\n"), - job_control_mode==JOB_CONTROL_INTERACTIVE?_(L"Only on interactive jobs"): - (job_control_mode==JOB_CONTROL_NONE ? _(L"Never") : _(L"Always"))); + streams.out.append_format( + _(L"Job control: %ls\n"), + job_control_mode == JOB_CONTROL_INTERACTIVE + ? _(L"Only on interactive jobs") + : (job_control_mode == JOB_CONTROL_NONE ? _(L"Never") : _(L"Always"))); streams.out.append(parser.stack_trace()); break; } @@ -3072,262 +2332,177 @@ static int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **arg return res; } - -/** - The exit builtin. Calls reader_exit to exit and returns the value specified. -*/ -static int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The exit builtin. Calls reader_exit to exit and returns the value specified. +static int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { int argc = builtin_count_args(argv); - long ec=0; - switch (argc) - { - case 1: - { + long ec = 0; + switch (argc) { + case 1: { ec = proc_get_last_status(); break; } - - case 2: - { + case 2: { wchar_t *end; errno = 0; - ec = wcstol(argv[1],&end,10); - if (errno || *end != 0) - { - streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"), - argv[0], - argv[1]); + ec = wcstol(argv[1], &end, 10); + if (errno || *end != 0) { + streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"), argv[0], + argv[1]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } break; } - - default: - { - streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS, - argv[0]); + default: { + streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - } reader_exit(1, 0); return (int)ec; } -/** - 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. -*/ -static int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// 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. +static int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { env_var_t dir_in; wcstring dir; - int res=STATUS_BUILTIN_OK; - + int res = STATUS_BUILTIN_OK; - if (argv[1] == NULL) - { + if (argv[1] == NULL) { dir_in = env_get_string(L"HOME"); - if (dir_in.missing_or_empty()) - { - streams.err.append_format(_(L"%ls: Could not find home directory\n"), - argv[0]); + if (dir_in.missing_or_empty()) { + streams.err.append_format(_(L"%ls: Could not find home directory\n"), argv[0]); } - } - else - { + } else { dir_in = env_var_t(argv[1]); } bool got_cd_path = false; - if (! dir_in.missing()) - { + if (!dir_in.missing()) { got_cd_path = path_get_cdpath(dir_in, &dir); } - if (!got_cd_path) - { - if (errno == ENOTDIR) - { - streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"), - argv[0], - dir_in.c_str()); - } - else if (errno == ENOENT) - { - streams.err.append_format(_(L"%ls: The directory '%ls' does not exist\n"), - argv[0], - dir_in.c_str()); - } - else if (errno == EROTTEN) - { - streams.err.append_format(_(L"%ls: '%ls' is a rotten symlink\n"), - argv[0], - dir_in.c_str()); + if (!got_cd_path) { + if (errno == ENOTDIR) { + streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"), argv[0], + dir_in.c_str()); + } else if (errno == ENOENT) { + streams.err.append_format(_(L"%ls: The directory '%ls' does not exist\n"), argv[0], + dir_in.c_str()); + } else if (errno == EROTTEN) { + streams.err.append_format(_(L"%ls: '%ls' is a rotten symlink\n"), argv[0], + dir_in.c_str()); - } - else - { + } else { streams.err.append_format(_(L"%ls: Unknown error trying to locate directory '%ls'\n"), - argv[0], - dir_in.c_str()); - + argv[0], dir_in.c_str()); } - - if (!get_is_interactive()) - { + if (!shell_is_interactive()) { streams.err.append(parser.current_line()); } res = 1; - } - else if (wchdir(dir) != 0) - { + } else if (wchdir(dir) != 0) { struct stat buffer; int status; status = wstat(dir, &buffer); - if (!status && S_ISDIR(buffer.st_mode)) - { - streams.err.append_format(_(L"%ls: Permission denied: '%ls'\n"), - argv[0], - dir.c_str()); + if (!status && S_ISDIR(buffer.st_mode)) { + streams.err.append_format(_(L"%ls: Permission denied: '%ls'\n"), argv[0], dir.c_str()); - } - else - { - - streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"), - argv[0], - dir.c_str()); + } else { + streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"), argv[0], dir.c_str()); } - if (!get_is_interactive()) - { + if (!shell_is_interactive()) { streams.err.append(parser.current_line()); } res = 1; - } - else if (!env_set_pwd()) - { - res=1; + } else if (!env_set_pwd()) { + res = 1; streams.err.append_format(_(L"%ls: Could not set PWD variable\n"), argv[0]); } return res; } -/** - 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) -{ +/// 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) { int argc; argc = builtin_count_args(argv); - streams.out.append_format( L"%d\n", argc-1); - return !(argc-1); + streams.out.append_format(L"%d\n", argc - 1); + return !(argc - 1); } -/** - Implementation of the builtin contains command, used to check if a - specified string is part of a list. - */ -static int builtin_contains(parser_t &parser, io_streams_t &streams, wchar_t ** argv) -{ +/// Implementation of the builtin contains command, used to check if a specified string is part of +/// a list. +static int builtin_contains(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; int argc; argc = builtin_count_args(argv); wchar_t *needle; bool should_output_index = false; - const struct woption long_options[] = - { - { L"help", no_argument, 0, 'h' } , - { L"index", no_argument, 0, 'i' }, - { 0, 0, 0, 0 } - }; + const struct woption long_options[] = { + {L"help", no_argument, 0, 'h'}, {L"index", no_argument, 0, 'i'}, {0, 0, 0, 0}}; - while (1) - { + while (1) { int opt_index = 0; - int opt = w.wgetopt_long(argc, - argv, - L"+hi", - long_options, - &opt_index); - if (opt == -1) - break; + int opt = w.wgetopt_long(argc, argv, L"+hi", long_options, &opt_index); + if (opt == -1) break; - switch (opt) - { - case 0: - assert(opt_index >= 0 && (size_t)opt_index < sizeof long_options / sizeof *long_options); - if (long_options[opt_index].flag != 0) - break; - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name); + switch (opt) { + case 0: { + assert(opt_index >= 0 && + (size_t)opt_index < sizeof long_options / sizeof *long_options); + if (long_options[opt_index].flag != 0) break; + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], + long_options[opt_index].name); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; - - - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; - - - case ':': - builtin_missing_argument(parser, streams, argv[0], argv[w.woptind-1]); + } + case ':': { + builtin_missing_argument(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - - case '?': - builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]); + } + case '?': { + builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; - - case 'i': + } + case 'i': { should_output_index = true; break; + } } - } needle = argv[w.woptind]; - if (!needle) - { + if (!needle) { streams.err.append_format(_(L"%ls: Key not specified\n"), argv[0]); - } - else - { - for (int i=w.woptind+1; i<argc; i++) - { - - if (!wcscmp(needle, argv[i])) - { - if (should_output_index) streams.out.append_format( L"%d\n", i-w.woptind); + } else { + for (int i = w.woptind + 1; i < argc; i++) { + if (!wcscmp(needle, argv[i])) { + if (should_output_index) streams.out.append_format(L"%d\n", i - w.woptind); return 0; } } } return 1; - } - -/** - The . (dot) builtin, sometimes called source. Evaluates the contents of a file. -*/ -static int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// The . (dot) builtin, sometimes called source. Evaluates the contents of a file. +static int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv) { ASSERT_IS_MAIN_THREAD(); int fd; int res = STATUS_BUILTIN_OK; @@ -3338,32 +2513,27 @@ static int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **arg const wchar_t *fn, *fn_intern; - if (argc < 2 || (wcscmp(argv[1], L"-") == 0)) - { + if (argc < 2 || (wcscmp(argv[1], L"-") == 0)) { fn = L"-"; fn_intern = fn; fd = dup(streams.stdin_fd); - } - else - { - - if ((fd = wopen_cloexec(argv[1], O_RDONLY)) == -1) - { - streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1]); + } else { + if ((fd = wopen_cloexec(argv[1], O_RDONLY)) == -1) { + streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"), + argv[0], argv[1]); builtin_wperror(L"source", streams); return STATUS_BUILTIN_ERROR; } - if (fstat(fd, &buf) == -1) - { + if (fstat(fd, &buf) == -1) { close(fd); - streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1]); + streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"), + argv[0], argv[1]); builtin_wperror(L"source", streams); return STATUS_BUILTIN_ERROR; } - if (!S_ISREG(buf.st_mode)) - { + if (!S_ISREG(buf.st_mode)) { close(fd); streams.err.append_format(_(L"%ls: '%ls' is not a file\n"), argv[0], argv[1]); return STATUS_BUILTIN_ERROR; @@ -3381,166 +2551,103 @@ static int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **arg parser.pop_block(); - if (res) - { - streams.err.append_format(_(L"%ls: Error while reading file '%ls'\n"), - argv[0], - fn_intern == intern_static(L"-") ? L"<stdin>" : fn_intern); - } - else - { + if (res) { + streams.err.append_format(_(L"%ls: Error while reading file '%ls'\n"), argv[0], + fn_intern == intern_static(L"-") ? L"<stdin>" : fn_intern); + } else { res = proc_get_last_status(); } - /* - Do not close fd after calling reader_read. reader_read - automatically closes it before calling eval. - */ - + // Do not close fd after calling reader_read. reader_read automatically closes it before calling + // eval. reader_pop_current_filename(); return res; } -/** - Make the specified job the first job of the job list. Moving jobs - around in the list makes the list reflect the order in which the - jobs were used. -*/ -static void make_first(job_t *j) -{ - job_promote(j); -} - +/// Make the specified job the first job of the job list. Moving jobs around in the list makes the +/// list reflect the order in which the jobs were used. +static void make_first(job_t *j) { job_promote(j); } -/** - Builtin for putting a job in the foreground -*/ -static int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ - job_t *j=NULL; - - if (argv[1] == 0) - { - /* - Select last constructed job (I.e. first job in the job que) - that is possible to put in the foreground - */ +/// Builtin for putting a job in the foreground. +static int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) { + job_t *j = NULL; + if (argv[1] == 0) { + // Select last constructed job (I.e. first job in the job que) that is possible to put in + // the foreground. job_iterator_t jobs; - while ((j = jobs.next())) - { + while ((j = jobs.next())) { if (job_get_flag(j, JOB_CONSTRUCTED) && (!job_is_completed(j)) && - ((job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND))) && job_get_flag(j, JOB_CONTROL))) - { + ((job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND))) && + job_get_flag(j, JOB_CONTROL))) { break; } } - if (!j) - { - streams.err.append_format(_(L"%ls: There are no suitable jobs\n"), - argv[0]); + if (!j) { + streams.err.append_format(_(L"%ls: There are no suitable jobs\n"), argv[0]); } - } - else if (argv[2] != 0) - { - /* - Specifying what more than one job to put to the foreground - is a syntax error, we still try to locate the job argv[1], - since we want to know if this is an ambigous job - specification or if this is an malformed job id - */ + } else if (argv[2] != 0) { + // Specifying what more than one job to put to the foreground is a syntax error, we still + // try to locate the job argv[1], since we want to know if this is an ambigous job + // specification or if this is an malformed job id. wchar_t *endptr; int pid; int found_job = 0; errno = 0; pid = fish_wcstoi(argv[1], &endptr, 10); - if (!(*endptr || errno)) - { + if (!(*endptr || errno)) { j = job_get_from_pid(pid); - if (j) - found_job = 1; + if (j) found_job = 1; } - if (found_job) - { - streams.err.append_format(_(L"%ls: Ambiguous job\n"), - argv[0]); - } - else - { - streams.err.append_format(_(L"%ls: '%ls' is not a job\n"), - argv[0], - argv[1]); + if (found_job) { + streams.err.append_format(_(L"%ls: Ambiguous job\n"), argv[0]); + } else { + streams.err.append_format(_(L"%ls: '%ls' is not a job\n"), argv[0], argv[1]); } builtin_print_help(parser, streams, argv[0], streams.err); - j=0; + j = 0; - } - else - { + } else { wchar_t *end; int pid; errno = 0; pid = abs(fish_wcstoi(argv[1], &end, 10)); - if (*end || errno) - { - streams.err.append_format(BUILTIN_ERR_NOT_NUMBER, - argv[0], - argv[1]); + if (*end || errno) { + streams.err.append_format(BUILTIN_ERR_NOT_NUMBER, argv[0], argv[1]); builtin_print_help(parser, streams, argv[0], streams.err); - } - else - { + } else { j = job_get_from_pid(pid); - if (!j || !job_get_flag(j, JOB_CONSTRUCTED) || job_is_completed(j)) - { - streams.err.append_format(_(L"%ls: No suitable job: %d\n"), - argv[0], - pid); + if (!j || !job_get_flag(j, JOB_CONSTRUCTED) || job_is_completed(j)) { + streams.err.append_format(_(L"%ls: No suitable job: %d\n"), argv[0], pid); builtin_print_help(parser, streams, argv[0], streams.err); - j=0; - } - else if (!job_get_flag(j, JOB_CONTROL)) - { - streams.err.append_format(_(L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n"), - argv[0], - pid, - j->command_wcstr()); + j = 0; + } else if (!job_get_flag(j, JOB_CONTROL)) { + streams.err.append_format(_(L"%ls: Can't put job %d, '%ls' to foreground because " + L"it is not under job control\n"), + argv[0], pid, j->command_wcstr()); builtin_print_help(parser, streams, argv[0], streams.err); - j=0; + j = 0; } } } - if (j) - { - if (streams.err_is_redirected) - { - streams.err.append_format(FG_MSG, - j->job_id, - j->command_wcstr()); - } - else - { - /* - If we aren't redirecting, send output to real stderr, - since stuff in sb_err won't get printed until the - command finishes. - */ - fwprintf(stderr, - FG_MSG, - j->job_id, - j->command_wcstr()); + if (j) { + if (streams.err_is_redirected) { + streams.err.append_format(FG_MSG, j->job_id, j->command_wcstr()); + } else { + // If we aren't redirecting, send output to real stderr, since stuff in sb_err won't get + // printed until the command finishes. + fwprintf(stderr, FG_MSG, j->job_id, j->command_wcstr()); } const wcstring ft = tok_first(j->command()); - if (! ft.empty()) - env_set(L"_", ft.c_str(), ENV_EXPORT); + if (!ft.empty()) env_set(L"_", ft.c_str(), ENV_EXPORT); reader_write_title(j->command()); make_first(j); @@ -3551,96 +2658,65 @@ static int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) return j != 0; } -/** - Helper function for builtin_bg() -*/ -static int send_to_bg(parser_t &parser, io_streams_t &streams, job_t *j, const wchar_t *name) -{ - if (j == 0) - { - streams.err.append_format(_(L"%ls: Unknown job '%ls'\n"), - L"bg", - name); +/// Helper function for builtin_bg(). +static int send_to_bg(parser_t &parser, io_streams_t &streams, job_t *j, const wchar_t *name) { + if (j == 0) { + streams.err.append_format(_(L"%ls: Unknown job '%ls'\n"), L"bg", name); builtin_print_help(parser, streams, L"bg", streams.err); return STATUS_BUILTIN_ERROR; - } - else if (!job_get_flag(j, JOB_CONTROL)) - { - streams.err.append_format(_(L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n"), - L"bg", - j->job_id, - j->command_wcstr()); + } else if (!job_get_flag(j, JOB_CONTROL)) { + streams.err.append_format( + _(L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n"), + L"bg", j->job_id, j->command_wcstr()); builtin_print_help(parser, streams, L"bg", streams.err); return STATUS_BUILTIN_ERROR; } - else - { - streams.err.append_format(_(L"Send job %d '%ls' to background\n"), - j->job_id, - j->command_wcstr()); - } + + streams.err.append_format(_(L"Send job %d '%ls' to background\n"), j->job_id, + j->command_wcstr()); make_first(j); job_set_flag(j, JOB_FOREGROUND, 0); job_continue(j, job_is_stopped(j)); return STATUS_BUILTIN_OK; } - -/** - Builtin for putting a job in the background -*/ -static int builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// Builtin for putting a job in the background. +static int builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv) { int res = STATUS_BUILTIN_OK; - if (argv[1] == 0) - { + if (argv[1] == 0) { job_t *j; job_iterator_t jobs; - while ((j = jobs.next())) - { - if (job_is_stopped(j) && job_get_flag(j, JOB_CONTROL) && (!job_is_completed(j))) - { + while ((j = jobs.next())) { + if (job_is_stopped(j) && job_get_flag(j, JOB_CONTROL) && (!job_is_completed(j))) { break; } } - if (!j) - { - streams.err.append_format(_(L"%ls: There are no suitable jobs\n"), - argv[0]); + if (!j) { + streams.err.append_format(_(L"%ls: There are no suitable jobs\n"), argv[0]); res = 1; - } - else - { + } else { res = send_to_bg(parser, streams, j, _(L"(default)")); } - } - else - { + } else { wchar_t *end; int i; int pid; int err = 0; - for (i=1; argv[i]; i++) - { - errno=0; + for (i = 1; argv[i]; i++) { + errno = 0; pid = fish_wcstoi(argv[i], &end, 10); - if (errno || pid < 0 || *end || !job_get_from_pid(pid)) - { - streams.err.append_format(_(L"%ls: '%ls' is not a job\n"), - argv[0], - argv[i]); + if (errno || pid < 0 || *end || !job_get_from_pid(pid)) { + streams.err.append_format(_(L"%ls: '%ls' is not a job\n"), argv[0], argv[i]); err = 1; break; } } - if (!err) - { - for (i=1; !res && argv[i]; i++) - { + if (!err) { + for (i = 1; !res && argv[i]; i++) { pid = fish_wcstoi(argv[i], 0, 10); res |= send_to_bg(parser, streams, job_get_from_pid(pid), *argv); } @@ -3650,48 +2726,36 @@ static int builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv) return res; } - -/** - 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) -{ - int is_break = (wcscmp(argv[0],L"break")==0); +/// 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) { + int is_break = (wcscmp(argv[0], L"break") == 0); int argc = builtin_count_args(argv); - - if (argc != 1) - { - streams.err.append_format(BUILTIN_ERR_UNKNOWN, - argv[0], - argv[1]); + if (argc != 1) { + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], argv[1]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - /* Find the index of the enclosing for or while loop. Recall that incrementing loop_idx goes 'up' to outer blocks */ + // Find the index of the enclosing for or while loop. Recall that incrementing loop_idx goes + // 'up' to outer blocks. size_t loop_idx; - for (loop_idx = 0; loop_idx < parser.block_count(); loop_idx++) - { + for (loop_idx = 0; loop_idx < parser.block_count(); loop_idx++) { const block_t *b = parser.block_at_index(loop_idx); - if (b->type() == WHILE || b->type() == FOR) - break; + if (b->type() == WHILE || b->type() == FOR) break; } - if (loop_idx >= parser.block_count()) - { - streams.err.append_format(_(L"%ls: Not inside of loop\n"), - argv[0]); + if (loop_idx >= parser.block_count()) { + streams.err.append_format(_(L"%ls: Not inside of loop\n"), argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - /* Skip blocks interior to the loop */ + // Skip blocks interior to the loop. size_t block_idx = loop_idx; - while (block_idx--) - { + while (block_idx--) { parser.block_at_index(block_idx)->skip = true; } @@ -3702,13 +2766,8 @@ static int builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar return STATUS_BUILTIN_OK; } -/** - 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) -{ +/// 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) { parser.push_block(new breakpoint_block_t()); reader_read(STDIN_FILENO, streams.io_chain ? *streams.io_chain : io_chain_t()); @@ -3718,61 +2777,49 @@ static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t * return proc_get_last_status(); } - -/** - Function for handling the \c return builtin -*/ -static int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// Function for handling the \c return builtin. +static int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv) { int argc = builtin_count_args(argv); int status = proc_get_last_status(); - switch (argc) - { - case 1: + switch (argc) { + case 1: { break; - case 2: - { + } + case 2: { wchar_t *end; errno = 0; - status = fish_wcstoi(argv[1],&end,10); - if (errno || *end != 0) - { - streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"), - argv[0], - argv[1]); + status = fish_wcstoi(argv[1], &end, 10); + if (errno || *end != 0) { + streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"), argv[0], + argv[1]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } break; } - default: - streams.err.append_format(_(L"%ls: Too many arguments\n"), - argv[0]); + default: { + streams.err.append_format(_(L"%ls: Too many arguments\n"), argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; + } } - /* Find the function block */ + // Find the function block. size_t function_block_idx; - for (function_block_idx = 0; function_block_idx < parser.block_count(); function_block_idx++) - { + for (function_block_idx = 0; function_block_idx < parser.block_count(); function_block_idx++) { const block_t *b = parser.block_at_index(function_block_idx); - if (b->type() == FUNCTION_CALL || b->type() == FUNCTION_CALL_NO_SHADOW) - break; + if (b->type() == FUNCTION_CALL || b->type() == FUNCTION_CALL_NO_SHADOW) break; } - if (function_block_idx >= parser.block_count()) - { - streams.err.append_format(_(L"%ls: Not inside of function\n"), - argv[0]); + if (function_block_idx >= parser.block_count()) { + streams.err.append_format(_(L"%ls: Not inside of function\n"), argv[0]); builtin_print_help(parser, streams, argv[0], streams.err); return STATUS_BUILTIN_ERROR; } - /* Skip everything up to (and then including) the function block */ - for (size_t i=0; i < function_block_idx; i++) - { + // Skip everything up to (and then including) the function block. + for (size_t i = 0; i < function_block_idx; i++) { block_t *b = parser.block_at_index(i); b->skip = true; } @@ -3780,11 +2827,8 @@ static int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **arg return status; } -/** - History of commands executed by user -*/ -static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +/// History of commands executed by user. +static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv) { int argc = builtin_count_args(argv); bool search_history = false; @@ -3794,18 +2838,15 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar bool clear_history = false; bool merge_history = false; - static const struct woption long_options[] = - { - { L"prefix", no_argument, 0, 'p' }, - { L"delete", no_argument, 0, 'd' }, - { L"search", no_argument, 0, 's' }, - { L"contains", no_argument, 0, 'c' }, - { L"save", no_argument, 0, 'v' }, - { L"clear", no_argument, 0, 'l' }, - { L"merge", no_argument, 0, 'm' }, - { L"help", no_argument, 0, 'h' }, - { 0, 0, 0, 0 } - }; + static const struct woption long_options[] = {{L"prefix", no_argument, 0, 'p'}, + {L"delete", no_argument, 0, 'd'}, + {L"search", no_argument, 0, 's'}, + {L"contains", no_argument, 0, 'c'}, + {L"save", no_argument, 0, 'v'}, + {L"clear", no_argument, 0, 'l'}, + {L"merge", no_argument, 0, 'm'}, + {L"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; int opt = 0; int opt_index = 0; @@ -3813,53 +2854,60 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar wgetopter_t w; history_t *history = reader_get_history(); - /* Use the default history if we have none (which happens if invoked non-interactively, e.g. from webconfig.py */ - if (! history) - history = &history_t::history_with_name(L"fish"); + // Use the default history if we have none (which happens if invoked non-interactively, e.g. + // from webconfig.py. + if (!history) history = &history_t::history_with_name(L"fish"); - while ((opt = w.wgetopt_long_only(argc, argv, L"pdscvl", long_options, &opt_index)) != EOF) - { - switch (opt) - { - case 'p': + while ((opt = w.wgetopt_long_only(argc, argv, L"pdscvl", long_options, &opt_index)) != EOF) { + switch (opt) { + case 'p': { search_prefix = true; break; - case 'd': + } + case 'd': { delete_item = true; break; - case 's': + } + case 's': { search_history = true; break; - case 'c': + } + case 'c': { break; - case 'v': + } + case 'v': { save_history = true; break; - case 'l': + } + case 'l': { clear_history = true; break; - case 'm': + } + case 'm': { merge_history = true; break; - case 'h': + } + case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; break; - case '?': - streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind-1]); + } + case '?': { + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; break; - default: - streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind-1]); + } + default: { + streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind - 1]); return STATUS_BUILTIN_ERROR; + } } } - /* Everything after is an argument */ + // Everything after is an argument. const wcstring_list_t args(argv + w.woptind, argv + argc); - if (argc == 1) - { + if (argc == 1) { wcstring full_history; history->get_string_representation(&full_history, wcstring(L"\n")); streams.out.append(full_history); @@ -3867,27 +2915,25 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar return STATUS_BUILTIN_OK; } - if (merge_history) - { + if (merge_history) { history->incorporate_external_changes(); return STATUS_BUILTIN_OK; } - if (search_history) - { + if (search_history) { int res = STATUS_BUILTIN_ERROR; - for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter) - { + for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter) { const wcstring &search_string = *iter; - if (search_string.empty()) - { - streams.err.append_format(BUILTIN_ERR_COMBO2, argv[0], L"Use --search with either --contains or --prefix"); + if (search_string.empty()) { + streams.err.append_format(BUILTIN_ERR_COMBO2, argv[0], + L"Use --search with either --contains or --prefix"); return res; } - history_search_t searcher = history_search_t(*history, search_string, search_prefix?HISTORY_SEARCH_TYPE_PREFIX:HISTORY_SEARCH_TYPE_CONTAINS); - while (searcher.go_backwards()) - { + history_search_t searcher = history_search_t( + *history, search_string, + search_prefix ? HISTORY_SEARCH_TYPE_PREFIX : HISTORY_SEARCH_TYPE_CONTAINS); + while (searcher.go_backwards()) { streams.out.append(searcher.current_string()); streams.out.append(L"\n"); res = STATUS_BUILTIN_OK; @@ -3896,10 +2942,8 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar return res; } - if (delete_item) - { - for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter) - { + if (delete_item) { + for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter) { wcstring delete_string = *iter; if (delete_string[0] == '"' && delete_string[delete_string.length() - 1] == '"') delete_string = delete_string.substr(1, delete_string.length() - 2); @@ -3909,14 +2953,12 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar return STATUS_BUILTIN_OK; } - if (save_history) - { + if (save_history) { history->save(); return STATUS_BUILTIN_OK; } - if (clear_history) - { + if (clear_history) { history->clear(); history->save(); return STATUS_BUILTIN_OK; @@ -3970,13 +3012,11 @@ int builtin_parse(parser_t &parser, io_streams_t &streams, wchar_t **argv) } #endif -int builtin_true(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +int builtin_true(parser_t &parser, io_streams_t &streams, wchar_t **argv) { return STATUS_BUILTIN_OK; } -int builtin_false(parser_t &parser, io_streams_t &streams, wchar_t **argv) -{ +int builtin_false(parser_t &parser, io_streams_t &streams, wchar_t **argv) { return STATUS_BUILTIN_ERROR; } @@ -4074,111 +3114,78 @@ static const builtin_data_t builtin_datas[] = { #define BUILTIN_COUNT (sizeof builtin_datas / sizeof *builtin_datas) -static const builtin_data_t *builtin_lookup(const wcstring &name) -{ +static const builtin_data_t *builtin_lookup(const wcstring &name) { const builtin_data_t *array_end = builtin_datas + BUILTIN_COUNT; const builtin_data_t *found = std::lower_bound(builtin_datas, array_end, name); - if (found != array_end && name == found->name) - { + if (found != array_end && name == found->name) { return found; } - else - { - return NULL; - } + return NULL; } -void builtin_init() -{ - for (size_t i=0; i < BUILTIN_COUNT; i++) - { +void builtin_init() { + for (size_t i = 0; i < BUILTIN_COUNT; i++) { intern_static(builtin_datas[i].name); } } -void builtin_destroy() -{ -} +void builtin_destroy() {} -int builtin_exists(const wcstring &cmd) -{ - return !!builtin_lookup(cmd); -} +int builtin_exists(const wcstring &cmd) { return !!builtin_lookup(cmd); } -/** - Return true if the specified builtin should handle it's own help, - false otherwise. -*/ -static int internal_help(const wchar_t *cmd) -{ +/// Return true if the specified builtin should handle it's own help, false otherwise. +static int internal_help(const wchar_t *cmd) { CHECK(cmd, 0); - return contains(cmd, L"for", L"while", L"function", - L"if", L"end", L"switch", L"case", L"count", L"printf"); + return contains(cmd, L"for", L"while", L"function", L"if", L"end", L"switch", L"case", L"count", + L"printf"); } +int builtin_run(parser_t &parser, const wchar_t *const *argv, io_streams_t &streams) { + int (*cmd)(parser_t & parser, io_streams_t & streams, const wchar_t *const *argv) = NULL; -int builtin_run(parser_t &parser, const wchar_t * const *argv, io_streams_t &streams) -{ - int (*cmd)(parser_t &parser, io_streams_t &streams, const wchar_t * const *argv)=NULL; - CHECK(argv, STATUS_BUILTIN_ERROR); CHECK(argv[0], STATUS_BUILTIN_ERROR); const builtin_data_t *data = builtin_lookup(argv[0]); - cmd = (int (*)(parser_t &parser, io_streams_t &streams, const wchar_t * const*))(data ? data->func : NULL); + cmd = (int (*)(parser_t & parser, io_streams_t & streams, const wchar_t *const *))( + data ? data->func : NULL); - if (argv[1] != 0 && !internal_help(argv[0])) - { - if (argv[2] == 0 && (parse_util_argument_is_help(argv[1], 0))) - { + if (argv[1] != 0 && !internal_help(argv[0])) { + if (argv[2] == 0 && (parse_util_argument_is_help(argv[1], 0))) { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; } } - if (data != NULL) - { - int status; - - status = cmd(parser, streams, argv); - return status; - - } - else - { - debug(0, UNKNOWN_BUILTIN_ERR_MSG, argv[0]); + if (data != NULL) { + return cmd(parser, streams, argv); } + + debug(0, UNKNOWN_BUILTIN_ERR_MSG, argv[0]); return STATUS_BUILTIN_ERROR; } - -wcstring_list_t builtin_get_names(void) -{ +wcstring_list_t builtin_get_names(void) { wcstring_list_t result; result.reserve(BUILTIN_COUNT); - for (size_t i=0; i < BUILTIN_COUNT; i++) - { + for (size_t i = 0; i < BUILTIN_COUNT; i++) { result.push_back(builtin_datas[i].name); } return result; } -void builtin_get_names(std::vector<completion_t> *list) -{ +void builtin_get_names(std::vector<completion_t> *list) { assert(list != NULL); list->reserve(list->size() + BUILTIN_COUNT); - for (size_t i=0; i < BUILTIN_COUNT; i++) - { + for (size_t i = 0; i < BUILTIN_COUNT; i++) { append_completion(list, builtin_datas[i].name); } } -wcstring builtin_get_desc(const wcstring &name) -{ +wcstring builtin_get_desc(const wcstring &name) { wcstring result; const builtin_data_t *builtin = builtin_lookup(name); - if (builtin) - { + if (builtin) { result = _(builtin->desc); } return result; |