114 lines
4.2 KiB
C++
114 lines
4.2 KiB
C++
/**
|
|
MIT License
|
|
|
|
Copyright (c) 2016 Claudio Maggioni
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
#include "shell.h"
|
|
namespace mshconsole {
|
|
|
|
Command::Command(const std::string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const std::vector<const char*> argv)) :
|
|
name(n), funcCommand(funcptr), optionNum(0){
|
|
checkObj();
|
|
}
|
|
|
|
void Command::addOption(const poptOption& a){
|
|
if(a.arg!=NULL&&a.arg!=nullptr&&a.arg!=0) throw InvalidOptionException{};
|
|
for(int i=0; i<opts.size(); i++)
|
|
if(strcmp((opts[i].longName),(a.longName))==0||
|
|
opts[i].shortName==a.shortName)
|
|
throw DuplicatedOptionException();
|
|
opts.push_back(a);
|
|
optionNum++;
|
|
}
|
|
|
|
int Command::execute(const struct Params& p, CommandExecutor* c, std::ostream& errorStream){
|
|
if(p.argc<=0) return -1;
|
|
|
|
// options a, b, c take integer arguments
|
|
// options f and g take no arguments
|
|
poptContext pc;
|
|
opts.push_back(POPT_TERMINATOR);
|
|
|
|
Datas datas;
|
|
for(int i=0; i<optionNum; i++){
|
|
Data* tmp = new Data(&opts[i]);
|
|
opts[i].arg=&(tmp->d);
|
|
datas.push_back(tmp);
|
|
}
|
|
|
|
// pc is the context for all popt-related functions
|
|
pc = poptGetContext(NULL, p.argc, const_cast<const char**>(p.argv), opts.data(), 0);
|
|
poptSetOtherOptionHelp(pc, "[ARG...]");
|
|
if (p.argc < 2 && opts.size()==0) {
|
|
poptPrintUsage(pc, stderr, 0);
|
|
return 1;
|
|
}
|
|
|
|
// process options and handle each val returned
|
|
int val;
|
|
while ((val = poptGetNextOpt(pc)) >= 0);
|
|
|
|
// poptGetNextOpt returns -1 when the final argument has been parsed
|
|
// otherwise an error occured
|
|
if (val != -1) {
|
|
errorStream << name << ": ";
|
|
switch(val) {
|
|
case POPT_ERROR_NOARG:
|
|
errorStream << "argument missing for an option\n";
|
|
return 1;
|
|
case POPT_ERROR_BADOPT:
|
|
errorStream << "option not found\n";
|
|
return 1;
|
|
case POPT_ERROR_BADNUMBER:
|
|
case POPT_ERROR_OVERFLOW:
|
|
errorStream << "option could not be converted to number\n";
|
|
return 1;
|
|
default:
|
|
errorStream << "unknown error in option processing\n";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
std::vector<const char*> nonOptionArgs;
|
|
while (poptPeekArg(pc) != NULL)
|
|
nonOptionArgs.push_back(const_cast<const char*>(poptGetArg(pc)));
|
|
|
|
return (*funcCommand)(c,datas,nonOptionArgs);
|
|
}
|
|
|
|
const std::string& Command::getName(){
|
|
return this->name;
|
|
}
|
|
|
|
Command::Command(const Command& old) : name(old.name) , funcCommand(old.funcCommand){
|
|
checkObj();
|
|
}
|
|
|
|
void Command::checkObj(){
|
|
for(unsigned int i=0; i<name.length(); i++){
|
|
if(!((name[i]>'a'&&name[i]<'z')||(name[i]>'A'&&name[i]<'Z'))){
|
|
throw CommandNameNotValidException();
|
|
}
|
|
}
|
|
}
|
|
const struct poptOption Command::POPT_TERMINATOR = {NULL,'\0',POPT_ARG_NONE,NULL,-1,NULL,NULL};
|
|
}
|