Start making more use of std exception classes
#include <signal.h>
#include <iostream>
#include <typeinfo>
#include <signal.h>
#include <iostream>
#include <typeinfo>
-#include "../debug/backtrace.h"
#include "../debug/demangle.h"
#include "../debug/demangle.h"
-#include "../time/units.h"
-#include "../time/utils.h"
/**
Constructs an instance of the registered application class and runs it. If the
/**
Constructs an instance of the registered application class and runs it. If the
-application throws a UsageError, the static usage() function is called.
+application throws a usage_error, a help message is printed. The GetOpt class
+will throw such exceptions automatically in error conditions.
This function can only be called once. The global main() function provided by
the library normally does it automatically at program startup.
This function can only be called once. The global main() function provided by
the library normally does it automatically at program startup.
{
app_ = starter_->create_app(argc, argv);
}
{
app_ = starter_->create_app(argc, argv);
}
- catch(const UsageError &e)
+ catch(const usage_error &e)
- starter_->usage(e.what(), argv[0], e.get_brief());
+ cerr<<e.what()<<'\n';
+ cerr<<e.help()<<'\n';
cerr<<"An uncaught exception occurred.\n";
cerr<<" type: "<<Debug::demangle(typeid(e).name())<<'\n';
cerr<<" what(): "<<e.what()<<'\n';
cerr<<"An uncaught exception occurred.\n";
cerr<<" type: "<<Debug::demangle(typeid(e).name())<<'\n';
cerr<<" what(): "<<e.what()<<'\n';
-
- const Exception *exc = dynamic_cast<const Exception *>(&e);
- if(exc && !exc->get_backtrace().get_frames().empty())
- {
- cerr<<" backtrace:\n";
- const list<Debug::Backtrace::StackFrame> &frames = exc->get_backtrace().get_frames();
- for(list<Debug::Backtrace::StackFrame>::const_iterator i=frames.begin(); i!=frames.end(); ++i)
- cerr<<" "<<*i<<'\n';
- }
-/**
-Prints a message describing the usage of the application. The default version
-will blame the programmer for being lazy.
-
-@param reason Why the function was called
-@param argv0 The value of argv[0], to be used in the message
-@param brief Whether to print a brief or long usage message
-*/
-void Application::usage(const char *reason, const char *, bool)
-{
- if(reason)
- cerr<<"UsageError: "<<reason<<'\n';
- cerr<<"The programmer was lazy and didn't write a usage() function for this application.\n";
-}
-
/**
Default main loop. Calls tick() repeatedly until exit() is called. A custom
main loop should monitor the done member variable and return exit_code.
/**
Default main loop. Calls tick() repeatedly until exit() is called. A custom
main loop should monitor the done member variable and return exit_code.
Application::Starter::Starter()
{
if(starter_)
Application::Starter::Starter()
{
if(starter_)
- throw InvalidState("Can't create more than one Starter instance");
+ throw logic_error("Can't create more than one Starter instance");
virtual ~Starter() { }
virtual Application *create_app(int, char **) = 0;
virtual ~Starter() { }
virtual Application *create_app(int, char **) = 0;
- virtual void usage(const char *, const char *, bool) = 0;
virtual ~Application() { }
static int run(int, char **, void * =0);
virtual ~Application() { }
static int run(int, char **, void * =0);
- static void usage(const char *, const char *, bool);
static void *get_data() { return data_; }
protected:
static void *get_data() { return data_; }
protected:
{
public:
Application *create_app(int argc, char **argv) { return new T(argc, argv); }
{
public:
Application *create_app(int argc, char **argv) { return new T(argc, argv); }
- void usage(const char *r, const char *a, bool b) { T::usage(r, a, b); }
};
static Starter starter_;
};
static Starter starter_;
+GetOpt::GetOpt():
+ help(false)
+{
+ add_option("help", help, NO_ARG).set_help("Displays this help");
+}
+
GetOpt::~GetOpt()
{
for(list<OptBase *>::iterator i=opts.begin(); i!=opts.end(); ++i)
GetOpt::~GetOpt()
{
for(list<OptBase *>::iterator i=opts.begin(); i!=opts.end(); ++i)
for(list<OptBase *>::iterator i=opts.begin(); i!=opts.end(); ++i)
if((*i)->get_short()==s)
return **i;
for(list<OptBase *>::iterator i=opts.begin(); i!=opts.end(); ++i)
if((*i)->get_short()==s)
return **i;
- throw UsageError(string("Unknown option -")+s);
+ throw usage_error(string("Unknown option -")+s);
}
GetOpt::OptBase &GetOpt::get_option(const string &l)
}
GetOpt::OptBase &GetOpt::get_option(const string &l)
for(list<OptBase *>::iterator i=opts.begin(); i!=opts.end(); ++i)
if((*i)->get_long()==l)
return **i;
for(list<OptBase *>::iterator i=opts.begin(); i!=opts.end(); ++i)
if((*i)->get_long()==l)
return **i;
- throw UsageError(string("Unknown option --")+l);
+ throw usage_error(string("Unknown option --")+l);
}
void GetOpt::operator()(unsigned argc, const char *const *argv)
{
}
void GetOpt::operator()(unsigned argc, const char *const *argv)
{
- unsigned i = 1;
- for(; i<argc;)
+ unsigned i = 1;
+ for(; i<argc;)
- if(!argv[i][2])
- break;
-
- i += process_long(argv+i);
+ if(argv[i][1]=='-')
+ {
+ if(!argv[i][2])
+ break;
+
+ i += process_long(argv+i);
+ }
+ else
+ i += process_short(argv+i);
- i += process_short(argv+i);
+ args.push_back(argv[i++]);
- else
- args.push_back(argv[i++]);
+
+ for(; i<argc; ++i)
+ args.push_back(argv[i]);
-
- for(; i<argc; ++i)
- args.push_back(argv[i]);
+ catch(const usage_error &e)
+ {
+ throw usage_error(e.what(), "Usage: "+generate_usage(argv[0]));
+ }
+
+ if(help)
+ throw usage_error(string("Help for ")+argv[0]+":", generate_help());
}
unsigned GetOpt::process_long(const char *const *argp)
}
unsigned GetOpt::process_long(const char *const *argp)
else if(opt.get_arg_type()==REQUIRED_ARG)
{
if(!argp[1])
else if(opt.get_arg_type()==REQUIRED_ARG)
{
if(!argp[1])
- throw UsageError("Premature end of arguments");
+ throw usage_error("--"+string(arg)+" requires an argument");
// Process the next argument as option argument
opt.process(argp[1]);
// Process the next argument as option argument
opt.process(argp[1]);
else if(opt.get_arg_type()==REQUIRED_ARG)
{
if(!argp[1])
else if(opt.get_arg_type()==REQUIRED_ARG)
{
if(!argp[1])
- throw UsageError("Premature end of arguments");
+ throw usage_error("-"+string(1, *arg)+" requires an argument");
// Use the next argument as option argument
opt.process(argp[1]);
// Use the next argument as option argument
opt.process(argp[1]);
void GetOpt::OptBase::process()
{
if(arg_type==REQUIRED_ARG)
void GetOpt::OptBase::process()
{
if(arg_type==REQUIRED_ARG)
- throw UsageError("--"+lng+" requires an argument");
+ throw usage_error("--"+lng+" requires an argument");
void GetOpt::OptBase::process(const string &arg)
{
if(arg_type==NO_ARG)
void GetOpt::OptBase::process(const string &arg)
{
if(arg_type==NO_ARG)
- throw UsageError("--"+lng+" takes no argument");
+ throw usage_error("--"+lng+" takes no argument");
++seen_count;
store(arg);
++seen_count;
store(arg);
#ifndef MSP_CORE_GETOPT_H_
#define MSP_CORE_GETOPT_H_
#ifndef MSP_CORE_GETOPT_H_
#define MSP_CORE_GETOPT_H_
#include <string>
#include <vector>
#include <string>
#include <vector>
+class usage_error: public std::runtime_error
+{
+private:
+ std::string help_;
+
+public:
+ usage_error(const std::string &w, const std::string &h = std::string()): std::runtime_error(w), help_(h) { }
+ ~usage_error() throw() { }
+
+ const char *help() const throw() { return help_.c_str(); }
+};
+
+
std::istringstream ss(a);
ss>>tmp;
if(ss.fail())
std::istringstream ss(a);
ss>>tmp;
if(ss.fail())
- throw UsageError("Invalid argument for --"+lng);
+ throw usage_error("Invalid argument for --"+lng);
{
public:
ListOption(char s, const std::string &l, T &d, ArgType a): OptBase(s, l, a), data(d)
{
public:
ListOption(char s, const std::string &l, T &d, ArgType a): OptBase(s, l, a), data(d)
- { if(arg_type!=REQUIRED_ARG) throw Exception("ListOption with arg_type!=REQUIRED makes no sense"); }
+ { if(arg_type!=REQUIRED_ARG) throw std::invalid_argument("ListOption arg_type!=REQUIRED"); }
std::istringstream ss(a);
ss>>tmp;
if(ss.fail())
std::istringstream ss(a);
ss>>tmp;
if(ss.fail())
- throw UsageError("Invalid argument for --"+lng);
+ throw usage_error("Invalid argument for --"+lng);
std::list<OptBase *> opts;
std::vector<std::string> args;
public:
std::list<OptBase *> opts;
std::vector<std::string> args;
public:
~GetOpt();
const std::vector<std::string> &get_args() const { return args; }
~GetOpt();
const std::vector<std::string> &get_args() const { return args; }