150 lines
5.2 KiB
C++
150 lines
5.2 KiB
C++
#include "shell.h"
|
|
namespace mshconsole {
|
|
|
|
Command::Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector<char*> argv)) :
|
|
name(n), funcCommand(funcptr){
|
|
checkObj();
|
|
}
|
|
|
|
void Command::addOption(Option *a){
|
|
if(a->getOptionName().length()==1){
|
|
shortOpts.push_back(a);
|
|
}
|
|
else longOpts.push_back(a);
|
|
}
|
|
|
|
int Command::execute(const vector<string>* args, CommandExecutor* c){
|
|
if(args==nullptr) return -1;
|
|
|
|
//filling longData
|
|
Datas longData;
|
|
for(size_t i=0; i<longOpts.size(); i++){
|
|
longData.push_back(new Data(longOpts[i]));
|
|
}
|
|
|
|
//filling string for getopt and shortData
|
|
string getoptarg;
|
|
Datas shortData;
|
|
for(size_t i=0; i<shortOpts.size(); i++){
|
|
shortData.push_back(new Data(shortOpts[i]));
|
|
getoptarg.append(1,shortOpts[i]->getOptionName()[0]);
|
|
}
|
|
getoptarg+=" -:";
|
|
|
|
//creating argv as char** for getopt compatibility
|
|
vector<char *> argv(args->size());
|
|
size_t i;
|
|
for (i = 0; i < args->size(); ++i)
|
|
{
|
|
argv[i] = const_cast<char*>(&(args->operator[](i)[0]));
|
|
}
|
|
int argc=i;
|
|
|
|
//TODO: quotes for long options
|
|
try{
|
|
int c;
|
|
opterr=0;
|
|
optind=1;
|
|
while ((c = getopt (argc, argv.data(), getoptarg.c_str())) != -1){
|
|
if((c>='a'&&c<='z')||(c>='A'&&c>='Z')){
|
|
for(size_t i=0; i<shortOpts.size(); i++){
|
|
if(c==shortOpts[i]->getOptionName()[0]){
|
|
shortData[i]->set(true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if(c=='-'){
|
|
string l(optarg);
|
|
bool getout = false;
|
|
try{
|
|
for(size_t i=0; i<longOpts.size(); i++){
|
|
if(l.find(longOpts[i]->getOptionName()+"=")==0){
|
|
if(!(longOpts[i]->hasFlag(Option::STRING))){
|
|
throw NotRightArgException();
|
|
}
|
|
longData[i]->set(l.substr(longOpts[i]->getOptionName().size()+1,l.size()));
|
|
getout = true;
|
|
break;
|
|
}
|
|
if(l==longOpts[i]->getOptionName()){
|
|
longData[i]->set(true);
|
|
getout=true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch(Data::MultipleDefinitionException){
|
|
getout=false;
|
|
}
|
|
if(!getout) throw OptionNotParsedCorrectlyException(static_cast<string>("--") + optarg);
|
|
}
|
|
else if(c=='?'){
|
|
if (isprint (optopt))
|
|
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
|
|
else
|
|
fprintf (stderr, "Unknown option character `\\x%x'.\n",optopt);
|
|
return -1;
|
|
}
|
|
else //abort();
|
|
break;
|
|
}
|
|
|
|
//demo of all options for debug (code to check)
|
|
/*
|
|
for(size_t i=0; i<longOpts.size(); i++){
|
|
cout << longOpts[i]->getOptionName() << ": ";
|
|
LongData* now = data[i];
|
|
if(now->getState()==LongData::States::STRING) cout << now->getLongData();
|
|
else cout << now->getBoolState();
|
|
cout << "\n";
|
|
}
|
|
for(size_t i=0; i<shortOpts.size(); i++){
|
|
cout << shortOptions[i] << ": " << sLongData[i] << "\n";
|
|
}*/
|
|
}
|
|
catch(OptionNotParsedCorrectlyException e){
|
|
cout << "Error parsing option " << e.getOptarg() << "\n";
|
|
return -1;
|
|
}
|
|
catch(NotRightArgException){
|
|
cout << "Error on options argument type\n";
|
|
return -1;
|
|
}
|
|
|
|
//making one big Data vector
|
|
shortOpts.insert(
|
|
shortOpts.end(),
|
|
std::make_move_iterator(longOpts.begin()),
|
|
std::make_move_iterator(longOpts.end())
|
|
);
|
|
|
|
//deleting options and command name from argv
|
|
argv.erase(argv.begin()); //argv[0] = command name
|
|
for(int i=0; i<argv.size(); i++){
|
|
if(argv[0][0]=='-'){
|
|
argv.erase(argv.begin()+i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
return (*funcCommand)(c,shortData, argv);
|
|
}
|
|
|
|
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 string Command::Data::EMPTY("");
|
|
}
|