summaryrefslogtreecommitdiff
path: root/lib/mlibc/options/glibc/generic/getopt-stubs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mlibc/options/glibc/generic/getopt-stubs.cpp')
-rw-r--r--lib/mlibc/options/glibc/generic/getopt-stubs.cpp253
1 files changed, 0 insertions, 253 deletions
diff --git a/lib/mlibc/options/glibc/generic/getopt-stubs.cpp b/lib/mlibc/options/glibc/generic/getopt-stubs.cpp
deleted file mode 100644
index d13d4eb..0000000
--- a/lib/mlibc/options/glibc/generic/getopt-stubs.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-#include <assert.h>
-#include <bits/ensure.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <frg/optional.hpp>
-#include <mlibc/debug.hpp>
-
-char *optarg;
-int optind = 1;
-int opterr = 1;
-int optopt;
-
-namespace {
-
-int __optpos = 1;
-
-enum GetoptMode {
- Short,
- Long,
- LongOnly,
-};
-
-int getopt_common(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, enum GetoptMode mode) {
- auto longopt_consume = [&](const char *arg, char *s, int k, bool colon) -> frg::optional<int> {
- // Consume the option and its argument.
- if(longopts[k].has_arg == required_argument) {
- if(s) {
- // Consume the long option and its argument.
- optarg = s + 1;
- optind++;
- }else if(argv[optind + 1]) {
- // Consume the long option.
- optind++;
-
- // Consume the option's argument.
- optarg = argv[optind];
- optind++;
- }else{
- /* If an error was detected, and the first character of optstring is not a colon,
- and the external variable opterr is nonzero (which is the default),
- getopt() prints an error message. */
- if(!colon && opterr)
- fprintf(stderr, "--%s requires an argument.\n", arg);
- /* If the first character of optstring is a colon (':'), then getopt()
- returns ':' instead of '?' to indicate a missing option argument. */
- return colon ? ':' : '?';
- }
- }else if(longopts[k].has_arg == optional_argument) {
- if(s) {
- // Consume the long option and its argument.
- optarg = s + 1;
- optind++;
- }else{
- // Consume the long option.
- optarg = nullptr;
- optind++;
- }
- }else{
- __ensure(longopts[k].has_arg == no_argument);
-
- // Consume the long option.
- optind++;
- }
-
- return frg::null_opt;
- };
-
- bool colon = optstring[0] == ':';
- bool stop_at_first_nonarg = (optstring[0] == '+' || getenv("POSIXLY_CORRECT"));
-
- // glibc extension: Setting optind to zero causes a full reset.
- // TODO: Should we really reset opterr and the other flags?
- if(!optind
-#if __MLIBC_BSD_OPTION
- || optreset
-#endif //__MLIBC_BSD_OPTION
- ) {
- optarg = nullptr;
- optind = 1;
- opterr = 1;
- optopt = 0;
- __optpos = 1;
-#if __MLIBC_BSD_OPTION
- optreset = 0;
-#endif //__MLIBC_BSD_OPTION
- }
-
- auto isOptionArg = [](char *arg){
- // If the first character of arg '-', and the arg is not exactly
- // equal to "-" or "--", then the arg is an option argument.
- return arg[0] == '-' && strcmp(arg, "-") && strcmp(arg, "--");
- };
-
- while(optind < argc) {
- char *arg = argv[optind];
- if(!isOptionArg(arg)) {
- if(stop_at_first_nonarg) {
- return -1;
- }
-
- bool further_options = false;
- int skip = optind;
-
- for(; skip < argc; ++skip) {
- if(isOptionArg(argv[skip])) {
- further_options = true;
- break;
- }
- }
-
- if(further_options) {
- optind += skip - optind;
- continue;
- } else {
- optarg = nullptr;
- return -1;
- }
- }
-
- if(arg[1] == '-') {
- arg += 2;
-
- // Determine the end of the option name (vs. the start of the argument).
- auto s = strchr(arg, '=');
- size_t n = s ? (s - arg) : strlen(arg);
-
- int k = -1;
- for(int i = 0; longopts[i].name; i++) {
- if(strncmp(arg, longopts[i].name, n) || longopts[i].name[n])
- continue;
-
- if(k >= 0) {
- if(opterr)
- fprintf(stderr, "Multiple option declaration detected: %s\n", arg);
- return '?';
- }
- k = i;
- }
-
- if(k == -1) {
- if(opterr)
- fprintf(stderr, "--%s is not a valid option.\n", arg);
- return '?';
- }
-
- if(longindex)
- *longindex = k;
-
- if(auto r = longopt_consume(arg, s, k, colon); r)
- return r.value();
-
- if(!longopts[k].flag) {
- return longopts[k].val;
- }else{
- *longopts[k].flag = longopts[k].val;
- return 0;
- }
- }else{
- /* handle short options, i.e. options with only one dash prefixed; e.g. `program -s` */
- unsigned int i = __optpos;
- while(true) {
- if(mode == GetoptMode::LongOnly) {
- const char *lo_arg = &arg[1];
- auto s = strchr(lo_arg, '=');
- size_t n = s ? (s - lo_arg) : strlen(lo_arg);
- int k = -1;
-
- for(int longopt = 0; longopts[longopt].name; longopt++) {
- if(strncmp(lo_arg, longopts[longopt].name, n) || longopts[longopt].name[n])
- continue;
-
- if(k >= 0) {
- if(opterr)
- fprintf(stderr, "Multiple option declaration detected: %s\n", arg);
- return '?';
- }
-
- k = longopt;
- }
-
- if(k != -1) {
- if(auto r = longopt_consume(lo_arg, s, k, colon); r)
- return r.value();
-
- if(!longopts[k].flag) {
- return longopts[k].val;
- }else{
- *longopts[k].flag = longopts[k].val;
- return 0;
- }
- }
- }
-
- auto opt = strchr(optstring, arg[i]);
- if(opt) {
- if(opt[1] == ':') {
- bool required = (opt[2] != ':');
-
- if(arg[i+1]) {
- optarg = arg + i + 1;
- } else if(optind + 1 < argc && argv[optind + 1] && (required || argv[optind + 1][0] != '-')) {
- /* there is an argument to this short option, separated by a space */
- optarg = argv[optind + 1];
- optind++;
- __optpos = 1;
- } else if(!required) {
- optarg = nullptr;
- } else {
- __optpos = 1;
- optopt = arg[i];
- return colon ? ':' : '?';
- }
- optind++;
- } else {
- if(arg[i+1]) {
- __optpos++;
- } else if(arg[i]) {
- optind++;
- } else {
- return -1;
- }
- }
-
- return arg[i];
- } else {
- /* If getopt() does not recognize an option character, it prints an error message to stderr,
- stores the character in optopt, and returns '?'. The calling program may prevent
- the error message by setting opterr to 0. */
- optopt = arg[1];
- if(opterr)
- fprintf(stderr, "%s is not a valid option.\n", arg);
- return '?';
- }
- }
- }
- }
- return -1;
-}
-
-}
-
-int getopt_long(int argc, char * const argv[], const char *optstring,
- const struct option *longopts, int *longindex) {
- return getopt_common(argc, argv, optstring, longopts, longindex, GetoptMode::Long);
-}
-
-int getopt_long_only(int argc, char * const argv[], const char *optstring,
- const struct option *longopts, int *longindex) {
- return getopt_common(argc, argv, optstring, longopts, longindex, GetoptMode::LongOnly);
-}