msh-console/msh-console-library/command.cpp

91 lines
3 KiB
C++
Raw Normal View History

#include "shell.h"
namespace mshconsole {
Command::Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const 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){
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) {
cerr << name << ": ";
switch(val) {
case POPT_ERROR_NOARG:
cerr << "argument missing for an option\n";
return 1;
case POPT_ERROR_BADOPT:
cerr << "option not found\n";
return 1;
case POPT_ERROR_BADNUMBER:
case POPT_ERROR_OVERFLOW:
cerr << "option could not be converted to number\n";
return 1;
default:
cerr << "unknown error in option processing\n";
return 1;
}
}
vector<const char*> nonOptionArgs;
while (poptPeekArg(pc) != NULL)
nonOptionArgs.push_back(const_cast<const char*>(poptGetArg(pc)));
return (*funcCommand)(c,datas,nonOptionArgs);
}
const 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};
}