Clean up woption

1. Bravely use a real enum for has_arg, despite the warnings.

2. Use some C++11 initializers so we don't have to pass an int for this
   parameter.

No functional change expected here.
This commit is contained in:
ridiculousfish 2022-04-01 14:25:02 -07:00
parent ff72e3f154
commit a80e680125
30 changed files with 58 additions and 64 deletions

View file

@ -107,8 +107,7 @@ void builtin_wperror(const wchar_t *program_name, io_streams_t &streams) {
}
static const wchar_t *const short_options = L"+:h";
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'}, {}};
int parse_help_only_cmd_opts(struct help_only_cmd_opts_t &opts, int *optind, int argc,
const wchar_t **argv, parser_t &parser, io_streams_t &streams) {

View file

@ -66,7 +66,7 @@ static const struct woption long_options[] = {
{L"stop-nonopt", no_argument, nullptr, 's'}, {L"ignore-unknown", no_argument, nullptr, 'i'},
{L"name", required_argument, nullptr, 'n'}, {L"exclusive", required_argument, nullptr, 'x'},
{L"help", no_argument, nullptr, 'h'}, {L"min-args", required_argument, nullptr, 'N'},
{L"max-args", required_argument, nullptr, 'X'}, {nullptr, 0, nullptr, 0}};
{L"max-args", required_argument, nullptr, 'X'}, {}};
// Check if any pair of mutually exclusive options was seen. Note that since every option must have
// a short name we only need to check those.
@ -454,7 +454,7 @@ static void populate_option_strings(const argparse_cmd_opts_t &opts, wcstring *s
const auto &opt_spec = kv.second;
if (opt_spec->short_flag_valid) short_options->push_back(opt_spec->short_flag);
int arg_type = no_argument;
woption_argument_t arg_type = no_argument;
if (opt_spec->num_allowed == -1) {
arg_type = optional_argument;
if (opt_spec->short_flag_valid) short_options->append(L"::");
@ -468,7 +468,7 @@ static void populate_option_strings(const argparse_cmd_opts_t &opts, wcstring *s
{opt_spec->long_flag.c_str(), arg_type, nullptr, opt_spec->short_flag});
}
}
long_options->push_back({nullptr, 0, nullptr, 0});
long_options->push_back(woption{});
}
static int validate_arg(parser_t &parser, const argparse_cmd_opts_t &opts, option_spec_t *opt_spec,

View file

@ -343,7 +343,7 @@ static int parse_cmd_opts(bind_cmd_opts_t &opts, int *optind, //!OCLINT(high nc
{L"sets-mode", required_argument, nullptr, 'm'},
{L"silent", no_argument, nullptr, 's'},
{L"user", no_argument, nullptr, 'u'},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
wgetopter_t w;

View file

@ -29,7 +29,7 @@ static int parse_cmd_opts(block_cmd_opts_t &opts, int *optind, //!OCLINT(high n
{L"local", no_argument, nullptr, 'l'},
{L"global", no_argument, nullptr, 'g'},
{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
wgetopter_t w;

View file

@ -23,7 +23,7 @@ static const wchar_t *const short_options = L":hnq";
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'},
{L"names", no_argument, nullptr, 'n'},
{L"query", no_argument, nullptr, 'q'},
{nullptr, 0, nullptr, 0}};
{}};
static int parse_cmd_opts(builtin_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv,
parser_t &parser, io_streams_t &streams) {

View file

@ -26,7 +26,7 @@ static const wchar_t *const short_options = L":ahqsv";
static const struct woption long_options[] = {
{L"help", no_argument, nullptr, 'h'}, {L"all", no_argument, nullptr, 'a'},
{L"quiet", no_argument, nullptr, 'q'}, {L"query", no_argument, nullptr, 'q'},
{L"search", no_argument, nullptr, 's'}, {nullptr, 0, nullptr, 0}};
{L"search", no_argument, nullptr, 's'}, {}};
static int parse_cmd_opts(command_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv,
parser_t &parser, io_streams_t &streams) {

View file

@ -170,7 +170,7 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
{L"paging-mode", no_argument, nullptr, 'P'},
{L"paging-full-mode", no_argument, nullptr, 'F'},
{L"is-valid", no_argument, nullptr, 1},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
wgetopter_t w;

View file

@ -168,7 +168,7 @@ maybe_t<int> builtin_complete(parser_t &parser, io_streams_t &streams, const wch
{L"help", no_argument, nullptr, 'h'},
{L"keep-order", no_argument, nullptr, 'k'},
{L"escape", no_argument, nullptr, opt_escape},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
wgetopter_t w;

View file

@ -19,9 +19,8 @@ struct contains_cmd_opts_t {
bool print_index = false;
};
static const wchar_t *const short_options = L"+:hi";
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'},
{L"index", no_argument, nullptr, 'i'},
{nullptr, 0, nullptr, 0}};
static const struct woption long_options[] = {
{L"help", no_argument, nullptr, 'h'}, {L"index", no_argument, nullptr, 'i'}, {}};
static int parse_cmd_opts(contains_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv,
parser_t &parser, io_streams_t &streams) {

View file

@ -20,8 +20,7 @@ struct exit_cmd_opts_t {
bool print_help = false;
};
static const wchar_t *const short_options = L":h";
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'}, {}};
static int parse_cmd_opts(exit_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method)
int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) {

View file

@ -53,7 +53,7 @@ static const struct woption long_options[] = {
{L"argument-names", required_argument, nullptr, 'a'},
{L"no-scope-shadowing", no_argument, nullptr, 'S'},
{L"inherit-variable", required_argument, nullptr, 'V'},
{nullptr, 0, nullptr, 0}};
{}};
/// \return the internal_job_id for a pid, or 0 if none.
/// This looks through both active and finished jobs.

View file

@ -59,7 +59,7 @@ static const struct woption long_options[] = {{L"erase", no_argument, nullptr, '
{L"verbose", no_argument, nullptr, 'v'},
{L"handlers", no_argument, nullptr, 'H'},
{L"handlers-type", required_argument, nullptr, 't'},
{nullptr, 0, nullptr, 0}};
{}};
static int parse_cmd_opts(functions_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method)
int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) {

View file

@ -70,7 +70,7 @@ static const struct woption long_options[] = {{L"prefix", no_argument, nullptr,
{L"clear", no_argument, nullptr, 4},
{L"merge", no_argument, nullptr, 5},
{L"reverse", no_argument, nullptr, 'R'},
{nullptr, 0, nullptr, 0}};
{}};
/// Remember the history subcommand and disallow selecting more than one history subcommand.
static bool set_hist_cmd(const wchar_t *cmd, hist_cmd_t *hist_cmd, hist_cmd_t sub_cmd,

View file

@ -122,7 +122,7 @@ maybe_t<int> builtin_jobs(parser_t &parser, io_streams_t &streams, const wchar_t
{L"command", no_argument, nullptr, 'c'}, {L"group", no_argument, nullptr, 'g'},
{L"help", no_argument, nullptr, 'h'}, {L"last", no_argument, nullptr, 'l'},
{L"pid", no_argument, nullptr, 'p'}, {L"quiet", no_argument, nullptr, 'q'},
{L"query", no_argument, nullptr, 'q'}, {nullptr, 0, nullptr, 0}};
{L"query", no_argument, nullptr, 'q'}, {}};
int opt;
wgetopter_t w;

View file

@ -40,7 +40,7 @@ static const wchar_t *const short_options = L"+:hs:b:";
static const struct woption long_options[] = {{L"scale", required_argument, nullptr, 's'},
{L"base", required_argument, nullptr, 'b'},
{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
{}};
static int parse_cmd_opts(math_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method)
int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) {

View file

@ -18,7 +18,7 @@ static const wchar_t *const short_options = L"LPh";
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'},
{L"logical", no_argument, nullptr, 'L'},
{L"physical", no_argument, nullptr, 'P'},
{nullptr, 0, nullptr, 0}};
{}};
maybe_t<int> builtin_pwd(parser_t &parser, io_streams_t &streams, const wchar_t **argv) {
UNUSED(parser);
const wchar_t *cmd = argv[0];

View file

@ -80,7 +80,7 @@ static const struct woption long_options[] = {{L"array", no_argument, nullptr, '
{L"tokenize", no_argument, nullptr, 't'},
{L"unexport", no_argument, nullptr, 'u'},
{L"universal", no_argument, nullptr, 'U'},
{nullptr, 0, nullptr, 0}};
{}};
static int parse_cmd_opts(read_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method)
int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) {
@ -505,7 +505,8 @@ maybe_t<int> builtin_read(parser_t &parser, io_streams_t &streams, const wchar_t
// if we're chunking we could get multiple lines so we would have to advance
// more than 1 per run through the loop. Let's skip that for now.
!opts.one_line &&
(streams.stdin_is_directly_redirected || lseek(streams.stdin_fd, 0, SEEK_CUR) != -1)) {
(streams.stdin_is_directly_redirected ||
lseek(streams.stdin_fd, 0, SEEK_CUR) != -1)) {
// We read in chunks when we either can seek (so we put the bytes back),
// or we have the bytes to ourselves (because it's directly redirected).
//
@ -513,7 +514,8 @@ maybe_t<int> builtin_read(parser_t &parser, io_streams_t &streams, const wchar_t
// under the assumption that the stream will be closed soon anyway.
// You don't rewind VHS tapes before throwing them in the trash.
// TODO: Do this when nchars is set by seeking back.
exit_res = read_in_chunks(streams.stdin_fd, buff, opts.split_null, !streams.stdin_is_directly_redirected);
exit_res = read_in_chunks(streams.stdin_fd, buff, opts.split_null,
!streams.stdin_is_directly_redirected);
} else {
exit_res =
read_one_char_at_a_time(streams.stdin_fd, buff, opts.nchars, opts.split_null);

View file

@ -22,9 +22,8 @@ struct realpath_cmd_opts_t {
};
static const wchar_t *const short_options = L"+:hs";
static const struct woption long_options[] = {{L"no-symlinks", no_argument, nullptr, 's'},
{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
static const struct woption long_options[] = {
{L"no-symlinks", no_argument, nullptr, 's'}, {L"help", no_argument, nullptr, 'h'}, {}};
static int parse_cmd_opts(realpath_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method)
int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) {

View file

@ -19,8 +19,7 @@ struct return_cmd_opts_t {
bool print_help = false;
};
static const wchar_t *const short_options = L":h";
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'}, {}};
static int parse_cmd_opts(return_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method)
int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) {

View file

@ -77,7 +77,7 @@ static const struct woption long_options[] = {{L"export", no_argument, nullptr,
{L"path", no_argument, nullptr, opt_path},
{L"unpath", no_argument, nullptr, opt_unpath},
{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
{}};
// Hint for invalid path operation with a colon.
#define BUILTIN_SET_MISMATCHED_ARGS _(L"%ls: You provided %d indexes but %d values\n")

View file

@ -97,7 +97,7 @@ static const struct woption long_options[] = {{L"background", required_argument,
{L"reverse", no_argument, nullptr, 'r'},
{L"version", no_argument, nullptr, 'v'},
{L"print-colors", no_argument, nullptr, 'c'},
{nullptr, 0, nullptr, 0}};
{}};
#ifdef __APPLE__
static char sitm_esc[] = "\x1B[3m";
@ -113,10 +113,11 @@ maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, const wc
#ifdef __APPLE__
// Hack in missing italics and dim capabilities omitted from MacOS xterm-256color terminfo
// Helps Terminal.app/iTerm
if ((!enter_italics_mode || enter_italics_mode == "") || (!enter_dim_mode || enter_dim_mode == "")) {
if ((!enter_italics_mode || enter_italics_mode == "") ||
(!enter_dim_mode || enter_dim_mode == "")) {
const auto term_prog = parser.vars().get(L"TERM_PROGRAM");
if (!term_prog.missing_or_empty() &&
(term_prog->as_string() == L"Apple_Terminal" || term_prog->as_string() == L"iTerm.app")) {
if (!term_prog.missing_or_empty() && (term_prog->as_string() == L"Apple_Terminal" ||
term_prog->as_string() == L"iTerm.app")) {
const auto term = parser.vars().get(L"TERM");
if (!term.missing_or_empty() && (term->as_string() == L"xterm-256color")) {
enter_italics_mode = sitm_esc;

View file

@ -129,7 +129,7 @@ static const struct woption long_options[] = {
{L"line", no_argument, nullptr, 'n'},
{L"line-number", no_argument, nullptr, 'n'},
{L"print-stack-trace", no_argument, nullptr, 't'},
{nullptr, 0, nullptr, 0}};
{}};
/// Remember the status subcommand and disallow selecting more than one status subcommand.
static bool set_status_cmd(const wchar_t *cmd, status_cmd_opts_t &opts, status_cmd_t sub_cmd,

View file

@ -22,7 +22,6 @@
#include <utility>
#include <vector>
#include "pcre2.h"
#include "../builtin.h"
#include "../common.h"
#include "../env.h"
@ -35,6 +34,7 @@
#include "../wgetopt.h"
#include "../wildcard.h"
#include "../wutil.h" // IWYU pragma: keep
#include "pcre2.h"
// How many bytes we read() at once.
// Bash uses 128 here, so we do too (see READ_CHUNK_SIZE).
@ -616,7 +616,7 @@ static const struct woption long_options[] = {{L"all", no_argument, nullptr, 'a'
{L"fields", required_argument, nullptr, 'f'},
{L"allow-empty", no_argument, nullptr, 'a'},
{L"width", required_argument, nullptr, 'w'},
{nullptr, 0, nullptr, 0}};
{}};
static const std::unordered_map<char, decltype(*handle_flag_N)> flag_to_function = {
{'N', handle_flag_N}, {'a', handle_flag_a}, {'c', handle_flag_c}, {'e', handle_flag_e},

View file

@ -37,7 +37,7 @@ static const struct woption long_options[] = {
{L"short", no_argument, nullptr, 's'}, {L"no-functions", no_argument, nullptr, 'f'},
{L"type", no_argument, nullptr, 't'}, {L"path", no_argument, nullptr, 'p'},
{L"force-path", no_argument, nullptr, 'P'}, {L"query", no_argument, nullptr, 'q'},
{L"quiet", no_argument, nullptr, 'q'}, {nullptr, 0, nullptr, 0}};
{L"quiet", no_argument, nullptr, 'q'}, {}};
static int parse_cmd_opts(type_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv,
parser_t &parser, io_streams_t &streams) {

View file

@ -218,7 +218,7 @@ maybe_t<int> builtin_ulimit(parser_t &parser, io_streams_t &streams, const wchar
{L"ptys", no_argument, nullptr, 'P'},
{L"threads", no_argument, nullptr, 'T'},
{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
wgetopter_t w;
@ -396,7 +396,8 @@ maybe_t<int> builtin_ulimit(parser_t &parser, io_streams_t &streams, const wchar
}
if (what == RLIMIT_UNKNOWN) {
streams.err.append_format(_(L"%ls: Resource limit not available on this operating system\n"), cmd);
streams.err.append_format(
_(L"%ls: Resource limit not available on this operating system\n"), cmd);
builtin_print_error_trailer(parser, streams.err, cmd);
return STATUS_INVALID_ARGS;
}

View file

@ -128,9 +128,8 @@ maybe_t<int> builtin_wait(parser_t &parser, io_streams_t &streams, const wchar_t
bool print_help = false;
static const wchar_t *const short_options = L":nh";
static const struct woption long_options[] = {{L"any", no_argument, nullptr, 'n'},
{L"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}};
static const struct woption long_options[] = {
{L"any", no_argument, nullptr, 'n'}, {L"help", no_argument, nullptr, 'h'}, {}};
int opt;
wgetopter_t w;

View file

@ -303,7 +303,7 @@ static int fish_parse_opt(int argc, char **argv, fish_cmd_opts_t *opts) {
{"private", no_argument, nullptr, 'P'},
{"help", no_argument, nullptr, 'h'},
{"version", no_argument, nullptr, 'v'},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
while ((opt = getopt_long(argc, argv, short_opts, long_opts, nullptr)) != -1) {

View file

@ -912,7 +912,7 @@ int main(int argc, char *argv[]) {
{"ansi", no_argument, nullptr, 2},
{"pygments", no_argument, nullptr, 3},
{"check", no_argument, nullptr, 'c'},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
while ((opt = getopt_long(argc, argv, short_opts, long_opts, nullptr)) != -1) {

View file

@ -303,7 +303,7 @@ static bool parse_flags(int argc, char **argv, bool *continuous_mode, bool *verb
{"help", no_argument, nullptr, 'h'},
{"version", no_argument, nullptr, 'v'},
{"verbose", no_argument, nullptr, 'V'},
{nullptr, 0, nullptr, 0}};
{}};
int opt;
bool error = false;
while (!error && (opt = getopt_long(argc, argv, short_opts, long_opts, nullptr)) != -1) {

View file

@ -138,6 +138,9 @@ class wgetopter_t {
bool missing_arg_return_colon = false;
};
// Names for the values of the `has_arg' field of `woption'.
enum woption_argument_t : int { no_argument = 0, required_argument = 1, optional_argument = 2 };
/// Describe the long-named options requested by the application. The LONG_OPTIONS argument to
/// getopt_long or getopt_long_only is a vector of `struct option' terminated by an element
/// containing a name which is zero.
@ -156,26 +159,19 @@ class wgetopter_t {
/// options that have a zero `flag' field, `getopt' returns the contents of the `val' field.
struct woption {
/// Long name for switch.
const wchar_t *name;
/// Must be one of no_argument, required_argument and optional_argument.
///
/// has_arg can't be an enum because some compilers complain about type mismatches in all the
/// code that assumes it is an int.
int has_arg;
const wchar_t *name{nullptr};
/// Must be one of no_argument, required_argument or optional_argument.
woption_argument_t has_arg{};
/// If non-null, the flag whose value should be set if this switch is encountered.
int *flag;
int *flag{nullptr};
/// If \c flag is non-null, this is the value that flag will be set to. Otherwise, this is the
/// return-value of the function call.
wchar_t val;
wchar_t val{L'\0'};
constexpr woption(const wchar_t *name, woption_argument_t has_arg, int *flag, wchar_t val)
: name(name), has_arg(has_arg), flag(flag), val(val) {}
constexpr woption() = default;
};
// Names for the values of the `has_arg' field of `struct option'.
/// Specifies that a switch does not accept an argument.
#define no_argument 0
/// Specifies that a switch requires an argument.
#define required_argument 1
/// Specifies that a switch accepts an optional argument.
#define optional_argument 2
#endif /* FISH_WGETOPT_H */