473,396 Members | 1,797 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

console programm with alias design

Hi,

I try to design a program which has to run on console. There is only one
exe/binary and depend on the calling name argv[0] the different
tasks/commands should be performed as aliases. It's the technique by
busybox or linux lvm tools in C and avoids a bunch of different
binaries. Now I want to write those using C++ classes and boost.

Ok, now I'm in design considerations. I have problems with the API for
this purpose.
This class starts as base class of all commands to be implemented:
---8<---
class CommandContext : public boost::noncopyable {
public:
virtual const std::string& name() const = 0;
};
--->8----

This is a sample command:
---8<---
namespace po = boost::program_options;

class FooCommand : public CommandContext {
public:
FooCommand();

public:
const std::string& name() const;

private:
std::string m_name;
po::options_description m_desc;
po::variables_map m_vm;
};

FooCommand::FooCommand()
: m_name("foo"),
m_desc("foo description")
{
m_desc.add_options()
("include-path,I",
po::value< vector<string()->composing(),
"include path")
;
}

const std::string& FooCommand::name() const {
return m_name;
}
--->8---

Similar another command's implementation:
---8<---
BarCommand::BarCommand()
: m_name("bar"),
m_desc("bar description")
{
m_desc.add_options()
("compression", po::value<int>(), "set compression level")
;
}
--->8---

and the app class self with main():

---8<---
namespace po = boost::program_options;
namespace fs = boost::filesystem;

class app : public boost::noncopyable {
public:
app(int argc, char **argv);
int exec();

private:
void setupCmdOptions();
void parse(int argc, char **argv);

private:
fs::path m_path;
po::options_description m_desc;
po::variables_map m_vm;
bool m_start;
bool m_alias;
};

int main(int argc, char **argv) {
try {
app a(argc, argv);
return a.exec();
}
catch(std::exception& e) {
cerr << e.what();
return 1;
}
catch(...) {
cerr << "unexpected exception";
return 1;
}
}

app::app(int argc, char **argv)
: m_path(argv[0], fs::native),
m_desc("Allowed options"),
m_start( true ),
m_alias( false )
{
setupCmdOptions();
parse(argc, argv);
}

/// Declare the supported options.
void app::setupCmdOptions() {
m_desc.add_options()
("help", "produce help message")
("version,v", "print version string")
;
}

void app::parse(int argc, char **argv) {
po::store(po::parse_command_line(argc, argv, m_desc), m_vm);
po::notify(m_vm);

if (m_vm.count("help")) {
cout << "This is app v0.8.15.\n\n"
<< "Usage: " << m_path.leaf() << " [options]\n\n";
cout << m_desc << "\n";
m_start = false;
return;
}

if (m_vm.count("version")) {
cout << "app v0.8.15\n";
}

}

int app::exec() {
if ( m_start )
cout << "Start app\n";

return 0;
}

The command classes should register self at the app class, using the
specific command line options (added to app's options_description /
variables_map. Therefore an "app help" lists the common help message,
"app foo help" the help for foo command only.

I suffer from the design of all the classes APIs. Using boost isn't the
problem yet :-)

Any ideas, short samples, help here?

Thanks
Olaf
Jul 10 '07 #1
1 1796
Olaf wrote:
Hi,

I try to design a program which has to run on console. There is only one
exe/binary and depend on the calling name argv[0] the different
tasks/commands should be performed as aliases. It's the technique by
busybox or linux lvm tools in C and avoids a bunch of different
binaries. Now I want to write those using C++ classes and boost.
You mean something like the following?

#include <string>
#include <map>

#include <iostream>
#include <ostream>

typedef int (*main_fct)( int, char** );
typedef std::map< std::string, main_fct registry;

int main_a ( int argn, char ** args ) {
std::cout << "a\n";
}

int main_b ( int argn, char ** args ) {
std::cout << "b\n";
}

int main ( int argn, char ** args ) {
registry main_table;
main_table[ "a" ] = &main_a;
main_table[ "b" ] = &main_b;
registry::iterator main_iter = main_table.find( args[0] );
if ( main_iter == main_table.end() ) {
std::cerr << "invocation by unknown name\n";
exit(-1);
}
return ( main_iter->second( argn, args ) );
}

Ok, now I'm in design considerations. I have problems with the API for
this purpose.
This class starts as base class of all commands to be implemented:
---8<---
class CommandContext : public boost::noncopyable {
public:
virtual const std::string& name() const = 0;
};
--->8----

This is a sample command:
---8<---
namespace po = boost::program_options;

class FooCommand : public CommandContext {
public:
FooCommand();

public:
const std::string& name() const;

private:
std::string m_name;
po::options_description m_desc;
po::variables_map m_vm;
};

FooCommand::FooCommand()
: m_name("foo"),
m_desc("foo description")
{
m_desc.add_options()
("include-path,I",
po::value< vector<string()->composing(),
"include path")
;
}

const std::string& FooCommand::name() const {
return m_name;
}
--->8---

Similar another command's implementation:
---8<---
BarCommand::BarCommand()
: m_name("bar"),
m_desc("bar description")
{
m_desc.add_options()
("compression", po::value<int>(), "set compression level")
;
}
--->8---

and the app class self with main():

---8<---
namespace po = boost::program_options;
namespace fs = boost::filesystem;

class app : public boost::noncopyable {
public:
app(int argc, char **argv);
int exec();

private:
void setupCmdOptions();
void parse(int argc, char **argv);

private:
fs::path m_path;
po::options_description m_desc;
po::variables_map m_vm;
bool m_start;
bool m_alias;
};

int main(int argc, char **argv) {
try {
app a(argc, argv);
return a.exec();
}
catch(std::exception& e) {
cerr << e.what();
return 1;
}
catch(...) {
cerr << "unexpected exception";
return 1;
}
}

app::app(int argc, char **argv)
: m_path(argv[0], fs::native),
m_desc("Allowed options"),
m_start( true ),
m_alias( false )
{
setupCmdOptions();
parse(argc, argv);
}

/// Declare the supported options.
void app::setupCmdOptions() {
m_desc.add_options()
("help", "produce help message")
("version,v", "print version string")
;
}

void app::parse(int argc, char **argv) {
po::store(po::parse_command_line(argc, argv, m_desc), m_vm);
po::notify(m_vm);

if (m_vm.count("help")) {
cout << "This is app v0.8.15.\n\n"
<< "Usage: " << m_path.leaf() << " [options]\n\n";
cout << m_desc << "\n";
m_start = false;
return;
}

if (m_vm.count("version")) {
cout << "app v0.8.15\n";
}

}

int app::exec() {
if ( m_start )
cout << "Start app\n";

return 0;
}

The command classes should register self at the app class, using the
specific command line options (added to app's options_description /
variables_map. Therefore an "app help" lists the common help message,
"app foo help" the help for foo command only.

I suffer from the design of all the classes APIs. Using boost isn't the
problem yet :-)

Any ideas, short samples, help here?
I have a very hard time relating the code you posted to the first paragraph.
Why does it need to be so complicated? I suspect there are other problems,
unrelated to the args[0] switch, that you are trying to solve here.
Best

Kai-Uwe Bux
Jul 10 '07 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: ES | last post by:
Hello, I have very simple console app that attempts to send an email using system.web.mail. I compiles and runs without any errors but doesn't send anything. I've checked the badmail folder,...
4
by: jabailo | last post by:
This is driving me crazy. I finally got the Remoting sample chat application working almost. When I run the chat client in VS.NET it goes into an endless loop -- that's because I assume that...
2
by: Boba | last post by:
Hi, I'm programming a WinForm application. I would like to enter commands that will send output that will help me to locate bugs in the future. I know that there is a way to send output by...
4
by: ttan | last post by:
Is there anyway we can write an Application project and also have an option for console where it take the command line for input? Thanks
6
by: Giojo | last post by:
Hello guys! I can't resolve this problem.. I want my programm in c# working with only console if there are some parameters, but if someone make double-click on the exe I want to start the graphic...
1
by: lavu | last post by:
I currently have a C# windows Application . I would like this App to work through an command line interface also. I would like to specify command line params, which should start the app and process...
1
by: Joachim | last post by:
Is there a way to set a timeout for the Console.ReadLine method?
7
by: | last post by:
Hi to everyone! I have an Apache Webserver running on Win2000. I try to start a console application an the server though PHP, with the functions exec() or passthru() but it doesn't work. The...
83
by: deppy_3 | last post by:
Hi.I am started learning Programm language C before some time.I am trying to make a programm about a very simple "sell shop".This programm hasn't got any compile problem but when i run it i face...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.