posix_getopt.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #include "posix_getopt.h"
  2. #include <util/generic/ptr.h>
  3. #include <ctype.h>
  4. namespace NLastGetopt {
  5. char* optarg;
  6. int optind;
  7. int optopt;
  8. int opterr;
  9. int optreset;
  10. static THolder<TOpts> Opts;
  11. static THolder<TOptsParser> OptsParser;
  12. int getopt_long_impl(int argc, char* const* argv, const char* optstring,
  13. const struct option* longopts, int* longindex, bool long_only) {
  14. if (!Opts || optreset == 1) {
  15. optarg = nullptr;
  16. optind = 1;
  17. opterr = 1;
  18. optreset = 0;
  19. Opts.Reset(new TOpts(TOpts::Default(optstring)));
  20. Opts->AllowSingleDashForLong_ = long_only;
  21. for (const struct option* o = longopts; o != nullptr && o->name != nullptr; ++o) {
  22. TOpt* opt;
  23. if ((unsigned)o->val < 0x80 && isalnum(o->val)) {
  24. opt = &Opts->CharOption(char(o->val));
  25. opt->AddLongName(o->name);
  26. } else {
  27. Opts->AddLongOption(o->name);
  28. opt = const_cast<TOpt*>(&Opts->GetLongOption(o->name));
  29. }
  30. opt->HasArg_ = EHasArg(o->has_arg);
  31. opt->UserValue(o->flag);
  32. }
  33. OptsParser.Reset(new TOptsParser(&*Opts, argc, (const char**)argv));
  34. }
  35. optarg = nullptr;
  36. try {
  37. if (!OptsParser->Next()) {
  38. return -1;
  39. } else {
  40. optarg = (char*)OptsParser->CurVal();
  41. optind = (int)OptsParser->Pos_;
  42. if (longindex && OptsParser->CurOpt())
  43. *longindex = (int)Opts->IndexOf(OptsParser->CurOpt());
  44. return OptsParser->CurOpt() ? OptsParser->CurOpt()->GetCharOr0() : 1;
  45. }
  46. } catch (const NLastGetopt::TException&) {
  47. return '?';
  48. }
  49. }
  50. int getopt_long(int argc, char* const* argv, const char* optstring,
  51. const struct option* longopts, int* longindex) {
  52. return getopt_long_impl(argc, argv, optstring, longopts, longindex, false);
  53. }
  54. int getopt_long_only(int argc, char* const* argv, const char* optstring,
  55. const struct option* longopts, int* longindex) {
  56. return getopt_long_impl(argc, argv, optstring, longopts, longindex, true);
  57. }
  58. // XXX: leading colon is not supported
  59. // XXX: updating optind by client is not supported
  60. int getopt(int argc, char* const* argv, const char* optstring) {
  61. return getopt_long(argc, argv, optstring, nullptr, nullptr);
  62. }
  63. }