/* 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