/*
This file is part of c++script.
c++script is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
c++script is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with c++script. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include "c++script.h"
using namespace std;
namespace cpps{
vector args;
std::vector options;
static std::string description;
option_base::option_base(const char _letter,
std::string_view _longname,
std::string_view _desc,
bool _mandatory,
bool _valueneeded,
bool _mayrepeat)
:letter(_letter), longname(_longname), desc(_desc)
,mandatory(_mandatory), valueneeded(_valueneeded), mayrepeat(_mayrepeat)
{
}
option_base::~option_base()
{
auto f = ranges::find(options,this);
if (f != options.end()) options.erase (f);
}
bool option_base::addval (std::string_view val)
{
nbseen++;
bool ret = setval(val);
if (nbseen > 1 && !mayrepeat){
cerr << format ("option -{} --{} may not be repeated\n",letter,longname);
ret = false;
}
return ret;
}
bool option_setval (std::string &val, std::string_view v, char letter, const string &longname)
{
val = v;
return true;
}
static bool option_validate (const std::from_chars_result &res, const char *end, std::string_view v, char letter, const string &longname)
{
bool ret = false;
if (res.ec == std::errc()){
if (res.ptr longname.size() > maxlen) maxlen = o->longname.size();
}
for (auto o:options){
if (o->letter == ' '){
cout << format ("\t --{:{}} {}\n",o->longname,maxlen,o->desc);
}else{
cout << format ("\t-{} --{:{}} {}\n",o->letter,o->longname,maxlen,o->desc);
}
if (o->mayrepeat){
cout << format ("\t{:{}} This option may be repeated\n"," ",maxlen+5);
}
if (o->defval.size() > 0){
cout << format ("\t{:{}} Default value is {}\n"," ",maxlen+5,o->defval);
}
}
cout << '\n';
exit (0);
}
void endoptions(int argc, char *argv[])
{
for (int i=1; i opthelp (' ',"help","Show this help screen");
bool some_errors = false;
for (unsigned i=0; iletter,o->longname,o->desc);
}
cout << '\n';
#endif
exit (0);
}else if (arg.size() > 0 && arg[0] == '-'){
int remove = 0;
if (arg.size() == 1){
cerr << "Incomplete option -\n";
some_errors = true;
break;
}else{
char letter = arg[1];
if (letter == '-'){
if (arg.size() == 2){
// -- means end of options
args.erase(args.begin()+i);
break;
}else{ // arg.size() > 2
auto pos = arg.find('=');
string optname,optvalue;
if (pos == string::npos){
optname = arg.substr(2);
}else{
optname = arg.substr(2,pos-2);
optvalue = arg.substr(pos+1);
}
option_base *opt = nullptr;
for (auto o:options){
if (o->longname == optname){
opt = o;
break;
}
}
if (opt == nullptr){
cerr << format ("Unknown option {}, ending\n",optname);
usage();
exit (-1);
}else if (!opt->valueneeded && optvalue.size()==0){
opt->enable();
remove = 1;
}else if (optvalue.size() > 0){
if (!opt->addval(optvalue)) some_errors = true;
remove = 1;
}else if (more){
if (!opt->addval(args[i+1])) some_errors = true;
remove = 2;
}else{
cerr << format ("option --{} incomplete\n",optname);
some_errors = true;
break;
}
}
}else{
option_base *opt = nullptr;
for (auto o:options){
if (o->letter == letter){
opt = o;
break;
}
}
if (opt == nullptr){
cerr << format ("Unknown option -{}, ending\n",letter);
usage();
exit (-1);
}else if (!opt->valueneeded && arg.size()==2){
opt->enable();
remove = 1;
}else if (arg.size() > 2){
if (!opt->addval(arg.substr(2))) some_errors = true;
remove = 1;
}else if (more){
if (!opt->addval(args[i+1])) some_errors = true;
remove = 2;
}else{
cerr << format ("option -{} incomplete\n",letter);
some_errors = true;
}
}
}
if (remove > 0){
args.erase(args.begin()+i,args.begin()+i+remove);
i--;
}
}else{
break;
}
}
if (some_errors) exit(-1);
if (opthelp.val){
usage();
}else{
for (auto o:options){
if (o->mandatory && o->nbseen == 0){
cerr << format ("Option -{} --{} is mandatory\n",o->letter,o->longname);
some_errors = true;
}
}
if (some_errors) usage();
}
}
void progdesc(std::string_view desc)
{
description = desc;
}
} // namespace cpps