From 7a4d96b6252524d639130aac9bd1b4111be3fde5 Mon Sep 17 00:00:00 2001 From: Waldemar Kozaczuk Date: Tue, 30 Apr 2019 23:49:38 -0400 Subject: [PATCH] Move getopt* files to libc folder and convert to C++ Signed-off-by: Waldemar Kozaczuk Message-Id: <20190501034939.12436-2-jwkozaczuk@gmail.com> --- Makefile | 4 +-- libc/misc/getopt.cc | 77 ++++++++++++++++++++++++++++++++++++++++ libc/misc/getopt_long.cc | 61 +++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 libc/misc/getopt.cc create mode 100644 libc/misc/getopt_long.cc diff --git a/Makefile b/Makefile index 2f68d9642e..2ef75600a6 100644 --- a/Makefile +++ b/Makefile @@ -1329,8 +1329,8 @@ libc += misc/error.o libc += misc/ffs.o musl += misc/get_current_dir_name.o libc += misc/gethostid.o -musl += misc/getopt.o -musl += misc/getopt_long.o +libc += misc/getopt.o +libc += misc/getopt_long.o musl += misc/getsubopt.o libc += misc/realpath.o libc += misc/backtrace.o diff --git a/libc/misc/getopt.cc b/libc/misc/getopt.cc new file mode 100644 index 0000000000..70a11414d3 --- /dev/null +++ b/libc/misc/getopt.cc @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include + +extern "C" { + +char *optarg; +int optind=1, opterr=1, optopt, __optpos, __optreset=0; + +#define optpos __optpos +weak_alias(__optreset, optreset); + +int getopt(int argc, char * const argv[], const char *optstring) +{ + int i; + wchar_t c, d; + int k, l; + char *optchar; + + if (!optind || __optreset) { + __optreset = 0; + __optpos = 0; + optind = 1; + } + + if (optind >= argc || !argv[optind] || argv[optind][0] != '-' || !argv[optind][1]) + return -1; + if (argv[optind][1] == '-' && !argv[optind][2]) + return optind++, -1; + + if (!optpos) optpos++; + if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) { + k = 1; + c = 0xfffd; /* replacement char */ + } + optchar = argv[optind]+optpos; + optopt = c; + optpos += k; + + if (!argv[optind][optpos]) { + optind++; + optpos = 0; + } + + for (i=0; (l = mbtowc(&d, optstring+i, MB_LEN_MAX)) && d!=c; i+=l>0?l:1); + + if (d != c) { + if (optstring[0] != ':' && opterr) { + write(2, argv[0], strlen(argv[0])); + write(2, ": illegal option: ", 18); + write(2, optchar, k); + write(2, "\n", 1); + } + return '?'; + } + if (optstring[i+1] == ':') { + if (optind >= argc) { + if (optstring[0] == ':') return ':'; + if (opterr) { + write(2, argv[0], strlen(argv[0])); + write(2, ": option requires an argument: ", 31); + write(2, optchar, k); + write(2, "\n", 1); + } + return '?'; + } + optarg = argv[optind++] + optpos; + optpos = 0; + } + return c; +} + +weak_alias(getopt, __posix_getopt); +} diff --git a/libc/misc/getopt_long.cc b/libc/misc/getopt_long.cc new file mode 100644 index 0000000000..fbde89fc5c --- /dev/null +++ b/libc/misc/getopt_long.cc @@ -0,0 +1,61 @@ +#include +#include +#include + +extern "C" { + +extern int __optpos, __optreset; + +static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) +{ + if (!optind || __optreset) { + __optreset = 0; + __optpos = 0; + optind = 1; + } + if (optind >= argc || !argv[optind] || argv[optind][0] != '-') return -1; + if ((longonly && argv[optind][1]) || + (argv[optind][1] == '-' && argv[optind][2])) + { + int i; + for (i=0; longopts[i].name; i++) { + const char *name = longopts[i].name; + char *opt = argv[optind]+1; + if (*opt == '-') opt++; + for (; *name && *name == *opt; name++, opt++); + if (*name || (*opt && *opt != '=')) continue; + if (*opt == '=') { + if (!longopts[i].has_arg) continue; + optarg = opt+1; + } else { + if (longopts[i].has_arg == required_argument) { + if (!(optarg = argv[++optind])) + return ':'; + } else optarg = NULL; + } + optind++; + if (idx) *idx = i; + if (longopts[i].flag) { + *longopts[i].flag = longopts[i].val; + return 0; + } + return longopts[i].val; + } + if (argv[optind][1] == '-') { + optind++; + return '?'; + } + } + return getopt(argc, argv, optstring); +} + +int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 0); +} + +int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 1); +} +}