fish-shell/src/builtin_exit.cpp
Kurtis Rader 37b8cfaeba avoid struct name clashes
Running the tests on travis revealed that some compilers (or at least
with some options) call the wrong struct constructor if there is more
than one struct with the same name but differing definitions.
2017-06-16 21:01:57 -07:00

89 lines
2.8 KiB
C++

// Implementation of the exit builtin.
#include "config.h" // IWYU pragma: keep
#include <errno.h>
#include <stddef.h>
#include "builtin.h"
#include "builtin_exit.h"
#include "common.h"
#include "fallback.h" // IWYU pragma: keep
#include "io.h"
#include "proc.h"
#include "reader.h"
#include "wgetopt.h"
#include "wutil.h" // IWYU pragma: keep
struct exit_cmd_opts_t {
bool print_help = false;
};
static const wchar_t *short_options = L"h";
static const struct woption long_options[] = {{L"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}};
static int parse_cmd_opts(exit_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method)
int argc, wchar_t **argv, parser_t &parser, io_streams_t &streams) {
UNUSED(parser);
UNUSED(streams);
wchar_t *cmd = argv[0];
int opt;
wgetopter_t w;
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
switch (opt) { //!OCLINT(too few branches)
case 'h': {
opts.print_help = true;
break;
}
case '?': {
// We would normally invoke builtin_unknown_option() and return an error.
// But for this command we want to let it try and parse the value as a negative
// return value.
*optind = w.woptind - 1;
return STATUS_CMD_OK;
}
default: {
DIE("unexpected retval from wgetopt_long");
break;
}
}
}
*optind = w.woptind;
return STATUS_CMD_OK;
}
/// The exit builtin. Calls reader_exit to exit and returns the value specified.
int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
const wchar_t *cmd = argv[0];
int argc = builtin_count_args(argv);
exit_cmd_opts_t opts;
int optind;
int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams);
if (retval != STATUS_CMD_OK) return retval;
if (opts.print_help) {
builtin_print_help(parser, streams, cmd, streams.out);
return STATUS_CMD_OK;
}
if (optind + 1 < argc) {
streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS, cmd);
builtin_print_help(parser, streams, cmd, streams.err);
return STATUS_INVALID_ARGS;
}
if (optind == argc) {
retval = proc_get_last_status();
} else {
retval = fish_wcstoi(argv[optind]);
if (errno) {
streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"), cmd,
argv[optind]);
builtin_print_help(parser, streams, cmd, streams.err);
return STATUS_INVALID_ARGS;
}
}
reader_exit(1, 0);
return retval;
}