diff --git a/include/extern/getopt.hpp b/include/extern/getopt.hpp index ec9fa4f7..8108f0c1 100644 --- a/include/extern/getopt.hpp +++ b/include/extern/getopt.hpp @@ -12,7 +12,7 @@ static constexpr int optional_argument = 2; // clang-format on extern char *musl_optarg; -extern int musl_optind, musl_opterr, musl_optopt, musl_optreset; +extern int musl_optind, musl_optopt; struct option { char const *name; @@ -21,8 +21,6 @@ struct option { int val; }; -int musl_getopt_long_only( - int argc, char **argv, char const *optstring, option const *longopts, int *idx -); +int musl_getopt_long_only(int argc, char **argv, char const *optstring, option const *longopts); #endif // RGBDS_EXTERN_GETOPT_HPP diff --git a/src/cli.cpp b/src/cli.cpp index 4922ff4c..e920aa07 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -94,8 +94,7 @@ void cli_ParseArgs( for (;;) { char *atFileName = nullptr; for (int ch; - (ch = musl_getopt_long_only(curArgc, curArgv, optString.c_str(), longOpts, nullptr)) - != -1;) { + (ch = musl_getopt_long_only(curArgc, curArgv, optString.c_str(), longOpts)) != -1;) { if (ch == 1 && musl_optarg[0] == '@') { atFileName = &musl_optarg[1]; break; diff --git a/src/extern/getopt.cpp b/src/extern/getopt.cpp index 74849170..0d9ddd78 100644 --- a/src/extern/getopt.cpp +++ b/src/extern/getopt.cpp @@ -14,30 +14,21 @@ #include "style.hpp" char *musl_optarg; -int musl_optind = 1, musl_opterr = 1, musl_optopt; -int musl_optreset = 0; +int musl_optind = 1, musl_optopt; + static int musl_optpos; -static void musl_getopt_msg(char const *msg, char const *param, size_t len) { - FILE *f = stderr; - - style_Set(f, STYLE_RED, true); - fputs("error: ", f); - style_Reset(f); - - if (fwrite(msg, strlen(msg), 1, f) && fwrite(param, 1, len, f) == len) { - putc('\n', f); - } +static void musl_getopt_msg(char const *msg, char const *param) { + style_Set(stderr, STYLE_RED, true); + fputs("error: ", stderr); + style_Reset(stderr); + fputs(msg, stderr); + fputs(param, stderr); + putc('\n', stderr); } -static int getopt(int argc, char *argv[], char const *optstring) { - int i; - wchar_t c, d; - int k, l; - char *optchar; - - if (!musl_optind || musl_optreset) { - musl_optreset = 0; +static int musl_getopt(int argc, char *argv[], char const *optstring) { + if (!musl_optind) { musl_optpos = 0; musl_optind = 1; } @@ -46,7 +37,9 @@ static int getopt(int argc, char *argv[], char const *optstring) { return -1; } - if (argv[musl_optind][0] != '-') { + char *argi = argv[musl_optind]; + + if (argi[0] != '-') { if (optstring[0] == '-') { musl_optarg = argv[musl_optind++]; return 1; @@ -54,26 +47,28 @@ static int getopt(int argc, char *argv[], char const *optstring) { return -1; } - if (!argv[musl_optind][1]) { + if (!argi[1]) { return -1; } - if (argv[musl_optind][1] == '-' && !argv[musl_optind][2]) { - return musl_optind++, -1; + if (argi[1] == '-' && !argi[2]) { + ++musl_optind; + return -1; } if (!musl_optpos) { ++musl_optpos; } - k = mbtowc(&c, argv[musl_optind] + musl_optpos, MB_LEN_MAX); + wchar_t c; + int k = mbtowc(&c, argi + musl_optpos, MB_LEN_MAX); if (k < 0) { k = 1; c = 0xFFFD; // replacement char } - optchar = argv[musl_optind] + musl_optpos; + char *optchar = argi + musl_optpos; musl_optpos += k; - if (!argv[musl_optind][musl_optpos]) { + if (!argi[musl_optpos]) { ++musl_optind; musl_optpos = 0; } @@ -82,8 +77,9 @@ static int getopt(int argc, char *argv[], char const *optstring) { ++optstring; } - i = 0; - d = 0; + int i = 0; + wchar_t d = 0; + int l; do { l = mbtowc(&d, optstring + i, MB_LEN_MAX); if (l > 0) { @@ -95,8 +91,8 @@ static int getopt(int argc, char *argv[], char const *optstring) { if (d != c || c == ':') { musl_optopt = c; - if (optstring[0] != ':' && musl_opterr) { - musl_getopt_msg("unrecognized option: ", optchar, k); + if (optstring[0] != ':') { + musl_getopt_msg("unrecognized option: ", optchar); } return '?'; } @@ -111,9 +107,7 @@ static int getopt(int argc, char *argv[], char const *optstring) { if (optstring[0] == ':') { return ':'; } - if (musl_opterr) { - musl_getopt_msg("option requires an argument: ", optchar, k); - } + musl_getopt_msg("option requires an argument: ", optchar); return '?'; } } @@ -122,25 +116,106 @@ static int getopt(int argc, char *argv[], char const *optstring) { static void permute(char **argv, int dest, int src) { char *tmp = argv[src]; - int i; - - for (i = src; i > dest; --i) { + for (int i = src; i > dest; --i) { argv[i] = argv[i - 1]; } argv[dest] = tmp; } -static int musl_getopt_long_core( - int argc, char **argv, char const *optstring, option const *longopts, int *idx, int longonly -); +static int + musl_getopt_long_core(int argc, char **argv, char const *optstring, option const *longopts) { + musl_optarg = 0; + if (char *argi = argv[musl_optind]; + !longopts || argi[0] != '-' + || ((!argi[1] || argi[1] == '-') && (argi[1] != '-' || !argi[2]))) { + return musl_getopt(argc, argv, optstring); + } -static int musl_getopt_long( - int argc, char **argv, char const *optstring, option const *longopts, int *idx, int longonly -) { - int ret, skipped, resumed; + bool colon = optstring[optstring[0] == '+' || optstring[0] == '-'] == ':'; + int i = 0, cnt = 0, match = 0; + char *arg = 0, *opt, *start = argv[musl_optind] + 1; - if (!musl_optind || musl_optreset) { - musl_optreset = 0; + for (; longopts[i].name; ++i) { + char const *name = longopts[i].name; + opt = start; + if (*opt == '-') { + ++opt; + } + while (*opt && *opt != '=' && *opt == *name) { + ++name; + ++opt; + } + if (*opt && *opt != '=') { + continue; + } + arg = opt; + match = i; + if (!*name) { + cnt = 1; + break; + } + ++cnt; + } + if (cnt == 1 && arg - start == mblen(start, MB_LEN_MAX)) { + int l = arg - start; + for (i = 0; optstring[i]; ++i) { + int j = 0; + while (j < l && start[j] == optstring[i + j]) { + ++j; + } + if (j == l) { + ++cnt; + break; + } + } + } + if (cnt == 1) { + i = match; + opt = arg; + ++musl_optind; + if (*opt == '=') { + if (!longopts[i].has_arg) { + musl_optopt = longopts[i].val; + if (colon) { + return '?'; + } + musl_getopt_msg("option does not take an argument: ", longopts[i].name); + return '?'; + } + musl_optarg = opt + 1; + } else if (longopts[i].has_arg == required_argument) { + musl_optarg = argv[musl_optind]; + if (!musl_optarg) { + musl_optopt = longopts[i].val; + if (colon) { + return ':'; + } + musl_getopt_msg("option requires an argument: ", longopts[i].name); + return '?'; + } + ++musl_optind; + } + if (longopts[i].flag) { + *longopts[i].flag = longopts[i].val; + return 0; + } + return longopts[i].val; + } + if (argv[musl_optind][1] == '-') { + musl_optopt = 0; + if (!colon) { + musl_getopt_msg( + cnt ? "option is ambiguous: " : "unrecognized option: ", argv[musl_optind] + 2 + ); + } + ++musl_optind; + return '?'; + } + return musl_getopt(argc, argv, optstring); +} + +int musl_getopt_long_only(int argc, char **argv, char const *optstring, option const *longopts) { + if (!musl_optind) { musl_optpos = 0; musl_optind = 1; } @@ -149,10 +224,10 @@ static int musl_getopt_long( return -1; } - skipped = musl_optind; + int skipped = musl_optind; if (optstring[0] != '+' && optstring[0] != '-') { - int i; - for (i = musl_optind;; ++i) { + int i = musl_optind; + for (;; ++i) { if (i >= argc || !argv[i]) { return -1; } @@ -162,129 +237,14 @@ static int musl_getopt_long( } musl_optind = i; } - resumed = musl_optind; - ret = musl_getopt_long_core(argc, argv, optstring, longopts, idx, longonly); + int resumed = musl_optind; + int ret = musl_getopt_long_core(argc, argv, optstring, longopts); if (resumed > skipped) { - int i, cnt = musl_optind - resumed; - - for (i = 0; i < cnt; ++i) { + int cnt = musl_optind - resumed; + for (int i = 0; i < cnt; ++i) { permute(argv, skipped, musl_optind - 1); } musl_optind = skipped + cnt; } return ret; } - -static int musl_getopt_long_core( - int argc, char **argv, char const *optstring, option const *longopts, int *idx, int longonly -) { - musl_optarg = 0; - if (longopts && argv[musl_optind][0] == '-' - && ((longonly && argv[musl_optind][1] && argv[musl_optind][1] != '-') - || (argv[musl_optind][1] == '-' && argv[musl_optind][2]))) { - int colon = optstring[optstring[0] == '+' || optstring[0] == '-'] == ':'; - int i, cnt, match = 0; - char *arg = 0, *opt, *start = argv[musl_optind] + 1; - - for (cnt = i = 0; longopts[i].name; ++i) { - char const *name = longopts[i].name; - - opt = start; - if (*opt == '-') { - ++opt; - } - while (*opt && *opt != '=' && *opt == *name) { - ++name; - ++opt; - } - if (*opt && *opt != '=') { - continue; - } - arg = opt; - match = i; - if (!*name) { - cnt = 1; - break; - } - ++cnt; - } - if (cnt == 1 && longonly && arg - start == mblen(start, MB_LEN_MAX)) { - int l = arg - start; - - for (i = 0; optstring[i]; ++i) { - int j = 0; - - while (j < l && start[j] == optstring[i + j]) { - ++j; - } - if (j == l) { - ++cnt; - break; - } - } - } - if (cnt == 1) { - i = match; - opt = arg; - ++musl_optind; - if (*opt == '=') { - if (!longopts[i].has_arg) { - musl_optopt = longopts[i].val; - if (colon || !musl_opterr) { - return '?'; - } - musl_getopt_msg( - "option does not take an argument: ", - longopts[i].name, - strlen(longopts[i].name) - ); - return '?'; - } - musl_optarg = opt + 1; - } else if (longopts[i].has_arg == required_argument) { - musl_optarg = argv[musl_optind]; - if (!musl_optarg) { - musl_optopt = longopts[i].val; - if (colon) { - return ':'; - } - if (!musl_opterr) { - return '?'; - } - musl_getopt_msg( - "option requires an argument: ", longopts[i].name, strlen(longopts[i].name) - ); - return '?'; - } - ++musl_optind; - } - if (idx) { - *idx = i; - } - if (longopts[i].flag) { - *longopts[i].flag = longopts[i].val; - return 0; - } - return longopts[i].val; - } - if (argv[musl_optind][1] == '-') { - musl_optopt = 0; - if (!colon && musl_opterr) { - musl_getopt_msg( - cnt ? "option is ambiguous: " : "unrecognized option: ", - argv[musl_optind] + 2, - strlen(argv[musl_optind] + 2) - ); - } - ++musl_optind; - return '?'; - } - } - return getopt(argc, argv, optstring); -} - -int musl_getopt_long_only( - int argc, char **argv, char const *optstring, option const *longopts, int *idx -) { - return musl_getopt_long(argc, argv, optstring, longopts, idx, 1); -}