#pragma once
#include "last_getopt.h"
#include <util/generic/ptr.h>
#include <util/generic/noncopyable.h>
// implementation of Opt class using last getopt
/*
short-options syntax:
opt-letter ::=
[^: ]
opt-string ::=
'+'|'-'?({opt-letter}':'{0,2})*
example: "AbCx:y:z::"
{A,b,C} options without argument
{x,y} options with argument
{z} option with optional argument
1. shortopts begins with '-' :=> RETURN_IN_ORDER
== non-option forces getopt to return 1 and to place non-option into optarg
2. shortopts begins with '+' :=> REQUIRE_ORDER
GetEnv(_POSIX_OPTION_ORDER) :=> REQUIRE_ORDER
== 1st non-option forces getopt to return EOF
3. default :=> PERMUTE
== exchange options with non-options and place all options first
4. '--' command line argument forces getopt to stop parsing and to return EOF
in any case
long options should begin by '+' sign
or when (_getopt_long_only = 1) by '-' sign
struct option {
char *name : option name
int has_arg: 0 | 1 | 2 = without | with | optional argument
int *flag : if (flag != 0) then getopt returns 0 and stores val into *flag
int val : if (flag == 0) then getopt returns val
}
Example:
struct option my_opts[] = {
{ "delete", 0, &deletion_flag, DEL }, -- returns 0, deletion_flag := DEL
{ "add", 1, NULL, 'a' }, -- returns 'a', argument in optarg
{ NULL }
}
*/
#define OPT_RETURN_IN_ORDER "-"
#define OPT_REQUIRE_ORDER "+"
#define OPT_DONT_STORE_ARG ((void*)0)
class Opt : TNonCopyable {
public:
enum HasArg { WithoutArg,
WithArg,
PossibleArg };
struct Ion {
const char* name;
HasArg has_arg;
int* flag;
int val;
};
private:
THolder<NLastGetopt::TOpts> Opts_;
THolder<NLastGetopt::TOptsParser> OptsParser_;
const Ion* Ions_;
bool GotError_;
void Init(int argc, char* argv[], const char* optString, const Ion* longOptions = nullptr, bool longOnly = false, bool isOpen = false);
public:
Opt(int argc, char* argv[], const char* optString, const Ion* longOptions = nullptr, bool longOnly = false, bool isOpen = false);
Opt(int argc, const char* argv[], const char* optString, const Ion* longOptions = nullptr, bool longOnly = false, bool isOpen = false);
// Get() means next
int Get();
int Get(int* longOptionIndex);
int operator()() {
return Get();
}
const char* GetArg() const {
return Arg;
}
TVector<TString> GetFreeArgs() const {
return NLastGetopt::TOptsParseResult(&*Opts_, GetArgC(), GetArgV()).GetFreeArgs();
}
// obsolete, use GetArg() instead
char* Arg; /* option argument if any or NULL */
int Ind; /* command line index */
bool Err; /* flag to print error messages */
int GetArgC() const;
const char** GetArgV() const;
void DummyHelp(IOutputStream& os = Cerr);
};
// call before getopt. returns non-negative int, removing it from arguments (not found: -1)
// Example: returns 11 for "progname -11abc", -1 for "progname -a11"
int opt_get_number(int& argc, char* argv[]);
#define OPTION_HANDLING_PROLOG \
{ \
int optlet; \
while (EOF != (optlet = opt.Get())) { \
switch (optlet) {
#define OPTION_HANDLING_PROLOG_ANON(S) \
{ \
Opt opt(argc, argv, (S)); \
int optlet; \
while (EOF != (optlet = opt.Get())) { \
switch (optlet) {
#define OPTION_HANDLE_BEGIN(opt) case opt: {
#define OPTION_HANDLE_END \
} \
break;
#define OPTION_HANDLE(opt, handle) \
OPTION_HANDLE_BEGIN(opt) \
handle; \
OPTION_HANDLE_END
#define OPTION_HANDLING_EPILOG \
default: \
ythrow yexception() << "unknown optlet"; \
} \
} \
}