Files
pvxs/tools/cliutil.cpp
2026-09-11 07:38:00 -07:00

85 lines
2.6 KiB
C++

/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvxs is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include "cliutil.h"
namespace pvxs {
bool operator==(const ArgVal& rhs, const ArgVal& lhs) {
return rhs.defined==lhs.defined && rhs.value==lhs.value;
}
GetOpt::GetOpt(int argc, char *argv[], const char *spec)
:argv0("<program name>")
{
if(argc>=1)
argv0 = argv[0];
bool allpos = false; // after "--", treat all remaining as positional
for(int i=1; i<argc; i++) {
const char * arg = argv[i];
if(!allpos && arg[0]=='-') {
arg++;
if(arg[0]=='-') {
if(arg[1]=='\0') { // "--"
allpos = true;
continue;
}
// "--..." not supported
arguments.emplace_back(-1, argv[i]);
continue;
}
// process as short args
for(; *arg; arg++) {
for(auto s=spec; *s; s++) {
if(*s==*arg) { // match
if(s[1]==':') { // need arg value
if(arg[1]=='\0') { // "-a", "value"
if(i+1==argc) {
// oops. no value
arguments.emplace_back('?', nullptr);
return;
}
arguments.emplace_back(*arg, argv[i+1]);
i++;
} else {
// "-avalue"
arguments.emplace_back(*arg, &arg[1]);
}
goto nextarg;
} else { // flag
arguments.emplace_back(*s, nullptr);
// continue scanning for more flags. eg. "-vv"
goto nextchar;
}
} else if(s[1]==':') {
s++;
}
}
// unrecognized
arguments.emplace_back(-1, nullptr);
break;
nextchar:
(void)0; // need a statement after label...
}
nextarg:
(void)0;
} else {
positional.push_back(arg);
// replicate POSIXLY_CORRECT= behavior. Require options before positional.
allpos = true;
}
success = true;
}
}
} // namespace pvxs