From 072c965ba5fef4c4f431b5fb7b520ec0ca807555 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Wed, 6 Nov 2019 00:40:55 +0100 Subject: [PATCH] Add musl's implementation of `getopt_long_only` Both `getopt_long` and `getopt_long_only` are GNU-specific, so we'll be copying musl's implementation for portability. This was retrieved as of commit 90251cf73dfdd44e7a3f085d236e89a7dff1b00b. musl is licensed as MIT, which is compatible (being identical...) to RGBDS'. The file is being copied as-is, without a copyright notice or attribution, but this is only to have a verbatim copy in the history. Those will be added in the next commit. --- include/extern/getopt.h | 30 ++++++++ src/extern/getopt.c | 148 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 include/extern/getopt.h create mode 100644 src/extern/getopt.c diff --git a/include/extern/getopt.h b/include/extern/getopt.h new file mode 100644 index 00000000..35cbd358 --- /dev/null +++ b/include/extern/getopt.h @@ -0,0 +1,30 @@ +#ifndef _GETOPT_H +#define _GETOPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +int getopt(int, char * const [], const char *); +extern char *optarg; +extern int optind, opterr, optopt, optreset; + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +int getopt_long(int, char *const *, const char *, const struct option *, int *); +int getopt_long_only(int, char *const *, const char *, const struct option *, int *); + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/extern/getopt.c b/src/extern/getopt.c new file mode 100644 index 00000000..6949ab1c --- /dev/null +++ b/src/extern/getopt.c @@ -0,0 +1,148 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include "stdio_impl.h" + +extern int __optpos, __optreset; + +static void permute(char *const *argv, int dest, int src) +{ + char **av = (char **)argv; + char *tmp = av[src]; + int i; + for (i=src; i>dest; i--) + av[i] = av[i-1]; + av[dest] = tmp; +} + +static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly); + +static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) +{ + int ret, skipped, resumed; + if (!optind || __optreset) { + __optreset = 0; + __optpos = 0; + optind = 1; + } + if (optind >= argc || !argv[optind]) return -1; + skipped = optind; + if (optstring[0] != '+' && optstring[0] != '-') { + int i; + for (i=optind; ; i++) { + if (i >= argc || !argv[i]) return -1; + if (argv[i][0] == '-' && argv[i][1]) break; + } + optind = i; + } + resumed = optind; + ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly); + if (resumed > skipped) { + int i, cnt = optind-resumed; + for (i=0; i