aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/getopt/small/posix_getopt.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/small/posix_getopt.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/getopt/small/posix_getopt.cpp')
-rw-r--r--library/cpp/getopt/small/posix_getopt.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/library/cpp/getopt/small/posix_getopt.cpp b/library/cpp/getopt/small/posix_getopt.cpp
new file mode 100644
index 0000000000..bd06f3499f
--- /dev/null
+++ b/library/cpp/getopt/small/posix_getopt.cpp
@@ -0,0 +1,77 @@
+#include "posix_getopt.h"
+
+#include <util/generic/ptr.h>
+
+#include <ctype.h>
+
+namespace NLastGetopt {
+ char* optarg;
+ int optind;
+ int optopt;
+ int opterr;
+ int optreset;
+
+ static THolder<TOpts> Opts;
+ static THolder<TOptsParser> OptsParser;
+
+ int getopt_long_impl(int argc, char* const* argv, const char* optstring,
+ const struct option* longopts, int* longindex, bool long_only) {
+ if (!Opts || optreset == 1) {
+ optarg = nullptr;
+ optind = 1;
+ opterr = 1;
+ optreset = 0;
+ Opts.Reset(new TOpts(TOpts::Default(optstring)));
+
+ Opts->AllowSingleDashForLong_ = long_only;
+
+ for (const struct option* o = longopts; o != nullptr && o->name != nullptr; ++o) {
+ TOpt* opt;
+ if ((unsigned)o->val < 0x80 && isalnum(o->val)) {
+ opt = &Opts->CharOption(char(o->val));
+ opt->AddLongName(o->name);
+ } else {
+ Opts->AddLongOption(o->name);
+ opt = const_cast<TOpt*>(&Opts->GetLongOption(o->name));
+ }
+ opt->HasArg_ = EHasArg(o->has_arg);
+ opt->UserValue(o->flag);
+ }
+
+ OptsParser.Reset(new TOptsParser(&*Opts, argc, (const char**)argv));
+ }
+
+ optarg = nullptr;
+
+ try {
+ if (!OptsParser->Next()) {
+ return -1;
+ } else {
+ optarg = (char*)OptsParser->CurVal();
+ optind = (int)OptsParser->Pos_;
+ if (longindex && OptsParser->CurOpt())
+ *longindex = (int)Opts->IndexOf(OptsParser->CurOpt());
+ return OptsParser->CurOpt() ? OptsParser->CurOpt()->GetCharOr0() : 1;
+ }
+ } catch (const NLastGetopt::TException&) {
+ return '?';
+ }
+ }
+
+ int getopt_long(int argc, char* const* argv, const char* optstring,
+ const struct option* longopts, int* longindex) {
+ return getopt_long_impl(argc, argv, optstring, longopts, longindex, false);
+ }
+
+ int getopt_long_only(int argc, char* const* argv, const char* optstring,
+ const struct option* longopts, int* longindex) {
+ return getopt_long_impl(argc, argv, optstring, longopts, longindex, true);
+ }
+
+ // XXX: leading colon is not supported
+ // XXX: updating optind by client is not supported
+ int getopt(int argc, char* const* argv, const char* optstring) {
+ return getopt_long(argc, argv, optstring, nullptr, nullptr);
+ }
+
+}