Started work on automated option (flags) handling. Current code is incomplete.
This commit is contained in:
parent
9e5ab340d9
commit
00d937f28c
8 changed files with 289 additions and 38 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
||||||
# Build folders
|
# Build folders
|
||||||
build-*
|
build-*
|
||||||
|
|
||||||
|
#internal test
|
||||||
|
msh-console-library/main.cpp
|
||||||
|
|
||||||
# Autosaves
|
# Autosaves
|
||||||
*.autosave
|
*.autosave
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,25 @@
|
||||||
# msh-console dynamic library by praticamentetilde (Claudio Maggioni)
|
# msh-console dynamic library by praticamentetilde (Claudio Maggioni)
|
||||||
# licensed with "The Unlicense"
|
# licensed with "The Unlicense"
|
||||||
|
|
||||||
project(msh-console-library)
|
project(msh-console-library)
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
# Create a library which includes the source listed.
|
set(compilable OFF)
|
||||||
# The extension is already found. Any number of sources could be listed here.
|
if(${compilable})
|
||||||
SET(CMAKE_CXX_FLAGS "-std=c++11")
|
SET(CMAKE_CXX_FLAGS "-std=c++11")
|
||||||
add_library (mshconsole SHARED command.cpp commandexecutor.cpp commandexecutor.h command.h commands.cpp shell.cpp shell.h)
|
FILE(GLOB sources *.cpp)
|
||||||
|
FILE(GLOB headers *.h)
|
||||||
|
|
||||||
|
set(lib OFF)
|
||||||
|
if(${lib})
|
||||||
|
MESSAGE( STATUS "Building .so.1")
|
||||||
|
#compile the library
|
||||||
|
# Create a library which includes the source listed.
|
||||||
|
# The extension is already found. Any number of sources could be listed here.
|
||||||
|
list(REMOVE_ITEM SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
|
||||||
|
add_library (mshconsole SHARED ${SRC_LIST})
|
||||||
|
else(${lib})
|
||||||
|
MESSAGE( STATUS "Building exec (debug only)")
|
||||||
|
add_executable(${PROJECT_NAME} ${sources} ${headers})
|
||||||
|
endif(${lib})
|
||||||
|
endif(${compilable})
|
||||||
|
|
|
@ -1,14 +1,106 @@
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
|
|
||||||
Command::Command(const string& n, int (*funcptr)(const vector<string>* args, CommandExecutor*)) : name(n) , funcCommand(funcptr){
|
Command::Command(const string& n, int (*funcptr)(CommandExecutor*,const vector<LongData*>&,const vector<bool>&, const char** argv)) :
|
||||||
|
name(n), funcCommand(funcptr){
|
||||||
checkObj();
|
checkObj();
|
||||||
numCom++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Command::execute(const vector<string>* args, CommandExecutor* ciao){
|
int Command::execute(const vector<string>* args, CommandExecutor* c){
|
||||||
if(args==nullptr) return -1;
|
if(args==nullptr) return -1;
|
||||||
return (*funcCommand)(args, ciao);
|
vector<LongData*> data;
|
||||||
|
for(size_t i=0; i<longOptions.size(); i++){
|
||||||
|
data.push_back(new LongData());
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<bool> sLongData;
|
||||||
|
for(size_t i=0; i<shortOptions.size(); i++){
|
||||||
|
sLongData.push_back(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
string getoptarg;
|
||||||
|
for(size_t i=0; i<shortOptions.size(); i++){
|
||||||
|
getoptarg.append(1,shortOptions[i]);
|
||||||
|
}
|
||||||
|
getoptarg+=" -:";
|
||||||
|
|
||||||
|
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<shortOptions.size(); i++){
|
||||||
|
if(c==shortOptions[i]){
|
||||||
|
sLongData[i]=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(c=='-'){
|
||||||
|
string l(optarg);
|
||||||
|
bool getout = false;
|
||||||
|
try{
|
||||||
|
for(size_t i=0; i<longOptions.size(); i++){
|
||||||
|
if(l.find(longOptions[i]->getArgName()+"=")==0){
|
||||||
|
if(!(longOptions.at(i)->hasFlag(LongOption::STRING))){
|
||||||
|
throw NotRightArgException();
|
||||||
|
}
|
||||||
|
data[i]->set(l.substr(longOptions[i]->getArgName().size()+1,l.size()));
|
||||||
|
getout = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(l==longOptions[i]->getArgName()){
|
||||||
|
data[i]->set(true);
|
||||||
|
getout=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(LongData::MultipleDefinitionException){
|
||||||
|
getout=false;
|
||||||
|
}
|
||||||
|
if(!getout) throw OptionNotParsedCorrectlyException(static_cast<string>("--") + optarg);
|
||||||
|
}
|
||||||
|
else if(c=='?'){
|
||||||
|
//if (optopt == 'c')
|
||||||
|
// fprintf (stderr, "Option -%c requires an argument.\n", optopt); else
|
||||||
|
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 for debug
|
||||||
|
/*
|
||||||
|
for(size_t i=0; i<longOptions.size(); i++){
|
||||||
|
cout << longOptions[i]->getArgName() << ": ";
|
||||||
|
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<shortOptions.size(); i++){
|
||||||
|
cout << shortOptions[i] << ": " << sLongData[i] << "\n";
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
catch(OptionNotParsedCorrectlyException e){
|
||||||
|
cout << "Error parsing option " << e.getOptarg() << "\n";
|
||||||
|
}
|
||||||
|
catch(NotRightArgException){
|
||||||
|
cout << "Error on options argument type\n";
|
||||||
|
}
|
||||||
|
return (*funcCommand)(c,data,sLongData, const_cast<const char**>(argv.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
string Command::getName(){
|
string Command::getName(){
|
||||||
|
@ -17,7 +109,6 @@ namespace mshconsole {
|
||||||
|
|
||||||
Command::Command(const Command& old) : name(old.name) , funcCommand(old.funcCommand){
|
Command::Command(const Command& old) : name(old.name) , funcCommand(old.funcCommand){
|
||||||
checkObj();
|
checkObj();
|
||||||
numCom++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command::checkObj(){
|
void Command::checkObj(){
|
||||||
|
@ -28,9 +119,52 @@ namespace mshconsole {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Command::Options *Command::getCmdOpts() const
|
||||||
|
{
|
||||||
|
return cmdOpts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command::setCmdOpts(Command::Options *value)
|
||||||
|
{
|
||||||
|
cmdOpts = value;
|
||||||
|
}
|
||||||
|
|
||||||
Command::~Command(){
|
Command::~Command(){
|
||||||
numCom--;
|
numCom--;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Command::numCom = 0;
|
unsigned int Command::numCom = 0;
|
||||||
|
|
||||||
|
const Command::Options *(Command::defaultOpts) = new Command::Options();
|
||||||
|
|
||||||
|
string Command::Options::Option::getOShort() const
|
||||||
|
{
|
||||||
|
return oShort;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command::Options::Option::setOShort(const string &value)
|
||||||
|
{
|
||||||
|
oShort = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string Command::Options::Option::getOLong() const
|
||||||
|
{
|
||||||
|
return oLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command::Options::Option::setOLong(const string &value)
|
||||||
|
{
|
||||||
|
oLong = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command::Options::addOption(Command::Options::Option *a){
|
||||||
|
for(size_t i=0; i<this->howMany(); i++){
|
||||||
|
if(a->getOShort()==(this->operator [](i)->getOShort())||a->getOLong()==(this->operator [](i)->getOLong())){
|
||||||
|
throw OptionNameConflictException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opts.push_back(a);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
const string Command::LongData::EMPTY("");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,106 @@ using std::vector;
|
||||||
namespace mshconsole{
|
namespace mshconsole{
|
||||||
class Command
|
class Command
|
||||||
{
|
{
|
||||||
|
class OptionNotParsedCorrectlyException {
|
||||||
|
string optarg;
|
||||||
|
public:
|
||||||
|
OptionNotParsedCorrectlyException(const string& s) : optarg(s) {}
|
||||||
|
string getOptarg(){
|
||||||
|
return optarg;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CommandNameNotValidException {};
|
||||||
|
class NotRightArgException {};
|
||||||
|
|
||||||
|
vector<char> shortOptions;
|
||||||
const string name;
|
const string name;
|
||||||
static unsigned int numCom;
|
|
||||||
int (*funcCommand)(const vector<string>*,CommandExecutor*);
|
|
||||||
void checkObj();
|
void checkObj();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Command(const string& n, int (*funcptr)(const vector<string>* args, CommandExecutor*));
|
class LongData{
|
||||||
|
public:
|
||||||
|
enum States{
|
||||||
|
STRING=4,
|
||||||
|
TRUE=2,
|
||||||
|
FALSE=1
|
||||||
|
};
|
||||||
|
class MultipleDefinitionException{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
string sLongData;
|
||||||
|
enum States state;
|
||||||
|
static const string EMPTY;
|
||||||
|
bool isSLongDataValorized;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LongData() : sLongData(), state(LongData::FALSE), isSLongDataValorized(false) {}
|
||||||
|
void set(bool b){
|
||||||
|
if(isSLongDataValorized) throw MultipleDefinitionException();
|
||||||
|
b ? state=LongData::TRUE : state=LongData::FALSE;
|
||||||
|
isSLongDataValorized=true;
|
||||||
|
}
|
||||||
|
void set(const string& s){
|
||||||
|
if(isSLongDataValorized) throw MultipleDefinitionException();
|
||||||
|
state=LongData::STRING;
|
||||||
|
sLongData=s;
|
||||||
|
isSLongDataValorized=true;
|
||||||
|
}
|
||||||
|
enum LongData::States getState() const{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
const string& getLongData() const{
|
||||||
|
if(state!=LongData::STRING) return EMPTY;
|
||||||
|
else return sLongData;
|
||||||
|
}
|
||||||
|
bool getBoolState() const{
|
||||||
|
return state!=LongData::FALSE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Command(const string& n, int (*funcptr)(CommandExecutor*, const vector<LongData*>&, const vector<bool>&, const char** argv));
|
||||||
Command(const Command&);
|
Command(const Command&);
|
||||||
~Command();
|
~Command();
|
||||||
string getName();
|
string getName();
|
||||||
int execute(const vector<string>*, CommandExecutor* ciao);
|
int execute(const vector<string>*, CommandExecutor*);
|
||||||
|
|
||||||
|
class LongOption{
|
||||||
|
string argName;
|
||||||
|
public:
|
||||||
|
enum States{
|
||||||
|
STRING=2,
|
||||||
|
BOOL=1
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
enum States want;
|
||||||
|
public:
|
||||||
|
LongOption(const string& s, enum States b) : argName(s), want(b) {}
|
||||||
|
enum States getWant() const{
|
||||||
|
return want;
|
||||||
|
}
|
||||||
|
const string& getArgName(){
|
||||||
|
return argName;
|
||||||
|
}
|
||||||
|
bool hasFlag(enum States s){
|
||||||
|
return want & s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void addLongOption(LongOption* a){
|
||||||
|
longOptions.push_back(a);
|
||||||
|
}
|
||||||
|
void addShortOption(char a){
|
||||||
|
shortOptions.push_back(a);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
vector<LongOption*> longOptions;
|
||||||
|
int (*funcCommand)(CommandExecutor*,const vector<LongData*>&, const vector<bool>&, const char** argv);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Command::LongOption::States operator|(Command::LongOption::States a, Command::LongOption::States b){
|
||||||
|
return static_cast<Command::LongOption::States>(static_cast<int>(a) | static_cast<int>(b));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class CommandNameNotValidException{};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // COMMAND_H
|
#endif // COMMAND_H
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "commandexecutor.h"
|
#include "commandexecutor.h"
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
CommandExecutor::CommandExecutor() {}
|
CommandExecutor::CommandExecutor() {}
|
||||||
void CommandExecutor::exit(){
|
void CommandExecutor::exit(int code){
|
||||||
throw CommandExecutor::ExitException();
|
throw CommandExecutor::ExitException(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,19 @@ namespace mshconsole{
|
||||||
class CommandExecutor
|
class CommandExecutor
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
class ExitException {};
|
class ExitException {
|
||||||
|
int code;
|
||||||
|
public:
|
||||||
|
int getCode(){
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
ExitException(int c=0) : code(c){}
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
virtual int executeCmd(std::vector<std::string>* args) = 0;
|
virtual int executeCmd(std::vector<std::string>* args) = 0;
|
||||||
virtual int executeCmd(const std::string& args) = 0;
|
virtual int executeCmd(const std::string& args) = 0;
|
||||||
virtual size_t howManyCmds() const = 0;
|
virtual size_t howManyCmds() const = 0;
|
||||||
void exit();
|
void exit(int code=0);
|
||||||
CommandExecutor();
|
CommandExecutor();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,23 +29,23 @@ namespace mshconsole {
|
||||||
notLoop = false;
|
notLoop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::launch(){
|
int Shell::launch(){
|
||||||
|
|
||||||
//launch setup
|
//launch setup
|
||||||
if(notLoop) {
|
if(notLoop) {
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
if(shellSetup!=0) {
|
if(shellSetup!=0) {
|
||||||
notLoop = true;
|
notLoop = true;
|
||||||
(*shellSetup)(this);
|
(*shellSetup)(this);
|
||||||
notLoop = false;
|
notLoop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//launch loop
|
//launch loop
|
||||||
string* line;
|
string* line;
|
||||||
vector<string>* args;
|
vector<string>* args;
|
||||||
int status;
|
int exitCode;
|
||||||
try{
|
try{
|
||||||
do {
|
do {
|
||||||
bool readSuccess;
|
bool readSuccess;
|
||||||
do{
|
do{
|
||||||
|
@ -60,15 +60,18 @@ namespace mshconsole {
|
||||||
}
|
}
|
||||||
}while(!readSuccess);
|
}while(!readSuccess);
|
||||||
args = split_line(line);
|
args = split_line(line);
|
||||||
status = executeCmd(args);
|
executeCmd(args);
|
||||||
delete args;
|
delete args;
|
||||||
} while (1);
|
} while (1);
|
||||||
} catch(CommandExecutor::ExitException) {}
|
} catch(CommandExecutor::ExitException c) {
|
||||||
|
exitCode=c.getCode();
|
||||||
|
}
|
||||||
|
|
||||||
//launch postSetup
|
//launch postSetup
|
||||||
if(shellPostSetup!=0) {
|
if(shellPostSetup!=0) {
|
||||||
shellPostSetup(this);
|
shellPostSetup(this);
|
||||||
}
|
}
|
||||||
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Shell::launchCmd(vector<string>* args)
|
int Shell::launchCmd(vector<string>* args)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstddef>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
//#include "commands.h"
|
//#include "commands.h"
|
||||||
|
@ -19,7 +20,6 @@ using std::cerr;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::istringstream;
|
using std::istringstream;
|
||||||
using std::nullptr_t;
|
|
||||||
|
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ namespace mshconsole {
|
||||||
size_t howMany() const;
|
size_t howMany() const;
|
||||||
int launch(const vector<string>* args, bool launchThread=false);
|
int launch(const vector<string>* args, bool launchThread=false);
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool undoingLine;
|
static bool undoingLine;
|
||||||
Commands cmds;
|
Commands cmds;
|
||||||
string ps;
|
string ps;
|
||||||
|
@ -59,7 +60,7 @@ namespace mshconsole {
|
||||||
void setPs(const string &value);
|
void setPs(const string &value);
|
||||||
string getName() const;
|
string getName() const;
|
||||||
void setName(const string &value);
|
void setName(const string &value);
|
||||||
void launch();
|
int launch();
|
||||||
void setShellSetup(void (*)(Shell *));
|
void setShellSetup(void (*)(Shell *));
|
||||||
void (*getShellSetup())(Shell*);
|
void (*getShellSetup())(Shell*);
|
||||||
void setShellPostSetup(void (*)(Shell *));
|
void setShellPostSetup(void (*)(Shell *));
|
||||||
|
|
Loading…
Reference in a new issue