///////////////////////////////////////////////////////////////////////////
// senf::console::Executor
-prefix_ void senf::console::Executor::operator()(ParseCommandInfo const & command,
- std::ostream & output)
+prefix_ void senf::console::Executor::execute(std::ostream & output,
+ ParseCommandInfo const & command)
{
SENF_LOG(( "Executing: " << command ));
try {
switch(command.builtin()) {
case ParseCommandInfo::NoBuiltin :
- traverseCommand(command.commandPath())(output, command.arguments());
+ traverseCommand(command.commandPath())(output, command);
break;
case ParseCommandInfo::BuiltinCD :
root().shared_from_this());
}
+prefix_ void senf::console::Executor::operator()(std::ostream & output,
+ ParseCommandInfo const & command)
+{
+ return execute(output, command);
+}
+
prefix_ senf::console::DirectoryNode & senf::console::Executor::cwd()
const
{
///////////////////////////////////////////////////////////////////////////
// Types
- typedef boost::iterator_range< ParseCommandInfo::argument_iterator> Arguments;
-
/// Thrown by built-in 'exit' command
struct ExitException {};
///\}
///////////////////////////////////////////////////////////////////////////
- void operator()(ParseCommandInfo const & command, std::ostream & output);
+ void execute(std::ostream & output, ParseCommandInfo const & command);
+ ///< Execute command
+ /**< Output will be written to \a output.
+ Same as operator()(). */
+
+ void operator()(std::ostream & output, ParseCommandInfo const & command);
///< Execute command
- /**< Output will be written to \a output. */
+ /**< Output will be written to \a output.
+ Same as execute(). */
DirectoryNode & cwd() const; ///< Current working directory
protected:
void setCommand(senf::console::ParseCommandInfo const & cmd) {
commands.push_back(cmd);
}
- void testCommand(std::ostream & os, senf::console::Executor::Arguments) {
+ void testCommand(std::ostream & os, senf::console::ParseCommandInfo const & command) {
os << "testCommand\n";
}
}
{
std::stringstream os;
parser.parse("cd dir1", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinCD );
BOOST_CHECK( &executor.cwd() == &senf::console::root()["dir1"] );
BOOST_CHECK_EQUAL( os.str(), "" );
{
std::stringstream os;
parser.parse("cd /dir2", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinCD );
BOOST_CHECK( &executor.cwd() == &senf::console::root()["dir2"] );
BOOST_CHECK_EQUAL( os.str(), "" );
{
std::stringstream os;
parser.parse("cd dir1", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinCD );
BOOST_CHECK( &executor.cwd() == &senf::console::root()["dir2"] );
BOOST_CHECK_EQUAL( os.str(), "invalid directory\n" );
{
std::stringstream os;
parser.parse("cd /", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinCD );
BOOST_CHECK( &executor.cwd() == &senf::console::root() );
BOOST_CHECK_EQUAL( os.str(), "" );
{
std::stringstream os;
parser.parse("ls", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS );
BOOST_CHECK_EQUAL( os.str(), "dir1/\ndir2/\n" );
}
{
std::stringstream os;
parser.parse("ls dir1", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS );
BOOST_CHECK_EQUAL( os.str(), "dir3/\n" );
}
{
std::stringstream os;
parser.parse("ls dir3", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS );
BOOST_CHECK_EQUAL( os.str(), "invalid directory\n" );
}
{
std::stringstream os;
parser.parse("dir1/dir3 { }", &setCommand);
- executor(commands.rbegin()[1], os);
+ executor(os, commands.rbegin()[1]);
BOOST_CHECK_EQUAL( commands.rbegin()[1].builtin(), senf::console::ParseCommandInfo::BuiltinPUSHD );
BOOST_CHECK( &executor.cwd() == &senf::console::root()["dir1"]["dir3"] );
BOOST_CHECK_EQUAL( os.str(), "" );
{
std::stringstream os;
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinPOPD );
BOOST_CHECK( &executor.cwd() == &senf::console::root() );
BOOST_CHECK_EQUAL( os.str(), "" );
std::stringstream os;
parser.parse("exit", &setCommand);
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinEXIT );
- BOOST_CHECK_THROW( executor(commands.back(), os), senf::console::Executor::ExitException );
+ BOOST_CHECK_THROW( executor(os, commands.back()), senf::console::Executor::ExitException );
BOOST_CHECK_EQUAL( os.str(), "" );
}
{
std::stringstream os;
parser.parse("help /dir2", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinHELP );
BOOST_CHECK_EQUAL( os.str(), "senf::console::DirectoryNode at /dir2\n\nHelptext\n" );
}
{
std::stringstream os;
parser.parse("dir2/test", &setCommand);
- executor(commands.back(), os);
+ executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::NoBuiltin );
BOOST_CHECK_EQUAL( os.str(), "testCommand\n" );
}
\code
// Define callback function.
- void mycommand(std::ostream & os, senf::console::Arguments const & args)
+ void mycommand(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
// ...
os << "!! Important message ...\n";
}
prefix_ void senf::console::SimpleCommandNode::v_execute(std::ostream & output,
- Arguments const & arguments)
+ ParseCommandInfo const & command)
const
{
- fn_(output, arguments);
+ fn_(output, command);
}
///////////////////////////////cc.e////////////////////////////////////////
}
prefix_ senf::console::DirectoryNode &
-senf::console::DirectoryNode::operator[](std::string const & name)
+senf::console::DirectoryNode::getDirectory(std::string const & name)
const
{
try {
SENF_WRAP_EXC(std::bad_cast)
}
+prefix_ senf::console::DirectoryNode &
+senf::console::DirectoryNode::operator[](std::string const & name)
+ const
+{
+ return getDirectory(name);
+}
+
prefix_ senf::console::CommandNode &
-senf::console::DirectoryNode::operator()(std::string const & name)
+senf::console::DirectoryNode::getCommand(std::string const & name)
const
{
try {
SENF_WRAP_EXC(std::bad_cast)
}
+prefix_ senf::console::CommandNode &
+senf::console::DirectoryNode::operator()(std::string const & name)
+ const
+{
+ return getCommand(name);
+}
+
prefix_ senf::console::DirectoryNode &
senf::console::DirectoryNode::mkdir(std::string const & name)
{
prefix_ senf::console::CommandNode::CommandNode()
{}
+prefix_ void senf::console::CommandNode::execute(std::ostream & output,
+ ParseCommandInfo const & command)
+ const
+{
+ v_execute(output, command);
+}
+
prefix_ void senf::console::CommandNode::operator()(std::ostream & output,
- Arguments const & arguments)
+ ParseCommandInfo const & command)
const
{
- v_execute(output, arguments);
+ execute(output, command);
}
///////////////////////////////////////////////////////////////////////////
\code
// Define callback function.
- void mycommand(std::ostream & os, senf::console::Arguments const & args)
+ void mycommand(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
// ...
os << "!! Important message ...\n";
.doc("Do the member operation");
}
- void member(std::ostream & os, senf::console::Arguments const & args)
+ void member(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
// ...
}
callback. The callback types which can be added are listed at \ref console_callbacks.
\code
- void callback(std::ostream & os, senf::console::Arguments const & args) { ... }
+ void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { ... }
// ...
myDirectory.add("foo",&callback);
\endcode
adding the node to the tree. If the name is empty or non-unique, a unique name will be
automatically provided.
- To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink()
- member. This call removes the node from it's parent and returns a (smart) node pointer.
+ To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink() or the
+ parents senf::console::DirectoryNode::remove() member. This call removes the node from it's
+ parent and returns a (smart) node pointer.
\li If you ignore the return value, the node (and it's children) will be deleted.
\li Alternatively, you may store away the node and re-attach it later.
\li To rename a node, unlink and re-add it with a different name.
\code
- myDirectory.add("bar", myDirectory("foo").unlink());
+ myDirectory.add("bar", myDirectory.remove("foo"));
\endcode
\subsection console_node_param Assigning additional node parameters
Another possibility is to traverse the tree explicitly. For this purpose, the operators '[]' and
'()' have been overloaded in senf::console::DirectoryNode.
\code
+ senf::console::root().getDirectory("myDirectory").getCommand("foo")
+ \\ or more concise but otherwise completely identical
senf::console::root()["myDirectory"]("foo")
\endcode
- The '[]' operator will return a senf::console::DirectoryNode whereas '()' will return a
- senf::console::CommandNode. If the node is not found or is not of the correct type, an exception
- will be raised.
+
+ getDirectory and the '[]' operator will return a senf::console::DirectoryNode whereas getCommand
+ and the '()' operator will return a senf::console::CommandNode. If the node is not found or is
+ not of the correct type, an exception will be raised.
\section console_object_dir Assigning a directory to an object instance
be saved and/or re-attached at some other place in the
tree. */
+ GenericNode & get(std::string const & name) const;
+ ///< Get child node
+ /**< \throws UnknownNodeNameException if a child \a name
+ does not exist */
+
+ DirectoryNode & getDirectory(std::string const & name) const;
+ ///< Get directory child node
+ /**< Same as operator[]
+ \throws UnknownNodeNameException if a child \a name
+ does not exist.
+ \throws std::bad_cast if the child \a name is not a
+ directory node. */
+
DirectoryNode & operator[](std::string const & name) const;
///< Get directory child node
- /**< \throws UnknownNodeNameException if a child \a name
+ /**< Same as getDirectory
+ \throws UnknownNodeNameException if a child \a name
does not exist.
\throws std::bad_cast if the child \a name is not a
directory node. */
- CommandNode & operator()(std::string const & name) const;
+ CommandNode & getCommand(std::string const & name) const;
///< Get command child node
- /**< \throws UnknownNodeNameException if a child \a name
+ /**< Same as operator()
+ \throws UnknownNodeNameException if a child \a name
does not exist
\throws std::bad_cast if the child \a name is not a
command node. */
- GenericNode & get(std::string const & name) const;
- ///< Get child node
- /**< \throws UnknownNodeNameException if a child \a name
- does not exist */
+ CommandNode & operator()(std::string const & name) const;
+ ///< Get command child node
+ /**< Same as getCommand()
+ \throws UnknownNodeNameException if a child \a name
+ does not exist
+ \throws std::bad_cast if the child \a name is not a
+ command node. */
DirectoryNode & mkdir(std::string const & name);
///< Create sub-directory node
template <class ForwardRange>
GenericNode & traverse(ForwardRange const & range);
///< Traverse node path starting at this node
- /**< The <tt>FordwareRange::value_type</tt> must be
+ /**< The <tt>ForwardRange::value_type</tt> must be
(convertible to) std::string. Each range element
constitutes a step along the node traversal.
The CommandNode is the base-class for the tree leaf nodes. Concrete command node
implementations are derived from this class.
- To execute a command, CommandNode::operator()() is called. This abstract virtual function
- must be implemented in a derived class.
+ To execute a command, CommandNode::operator()() or CommandNode::execute() is called.
\ingroup node_tree
*/
typedef boost::shared_ptr<CommandNode const> cptr;
typedef boost::weak_ptr<CommandNode> weak_ptr;
- typedef ParseCommandInfo::ArgumentsRange Arguments;
-
///////////////////////////////////////////////////////////////////////////
- void operator()(std::ostream & output, Arguments const & arguments) const;
+ void execute(std::ostream & output, ParseCommandInfo const & command) const;
///< Execute the command
- /**< \param[in] output stream where result messages may be
+ /**< Same as operator()()
+ \param[in] output stream where result messages may be
+ written to
+ \param[in] arguments command arguments. This is a
+ range of ranges of ArgumentToken instances. */
+
+ void operator()(std::ostream & output, ParseCommandInfo const & command) const;
+ ///< Execute the command
+ /**< Same as execute()
+ \param[in] output stream where result messages may be
written to
\param[in] arguments command arguments. This is a
range of ranges of ArgumentToken instances. */
#ifndef DOXYGEN
private:
#endif
- virtual void v_execute(std::ostream & output, Arguments const & arguments) const = 0;
+ virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const = 0;
///< Called to execute the command
/**< \param[in] output stream where result messages may be
written to
private:
};
- typedef CommandNode::Arguments Arguments;
-
/** \brief Most simple CommandNode implementation
This CommandNode implementation simply forwards the \a output and \a arguments arguments to
typedef boost::shared_ptr<SimpleCommandNode const> cptr;
typedef boost::weak_ptr<SimpleCommandNode> weak_ptr;
- typedef boost::function<void (std::ostream &, Arguments const &)> Function;
+ typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
private:
virtual void v_help(std::ostream & output) const;
- virtual void v_execute(std::ostream & output, Arguments const & arguments) const;
+ virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const;
Function fn_;
}
namespace {
- void callback(std::ostream & os, senf::console::SimpleCommandNode::Arguments arguments)
+ void callback(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
os << "callback";
}
namespace {
struct Functor {
- void operator()(std::ostream & os,
- senf::console::SimpleCommandNode::Arguments const &) {
+ void operator()(std::ostream & os, senf::console::ParseCommandInfo const &) {
os << "functor";
}
};
{
std::stringstream ss;
- senf::console::root()("fn1")(ss, info.arguments());
+ senf::console::root()("fn1")(ss, info);
BOOST_CHECK_EQUAL( ss.str(), "callback" );
}
{
std::stringstream ss;
- senf::console::root()("fn2")(ss, info.arguments());
+ senf::console::root()("fn2")(ss, info);
BOOST_CHECK_EQUAL( ss.str(), "functor" );
}
{
std::stringstream ss;
senf::console::ParseCommandInfo info;
- senf::console::root()("fn")(ss, info.arguments());
+ senf::console::root()("fn")(ss, info);
BOOST_CHECK_EQUAL( ss.str(), "callback" );
}
}
prefix_ void senf::console::OverloadedCommandNode::v_execute(std::ostream & output,
- Arguments const & arguments)
+ ParseCommandInfo const & command)
const
{
Overloads::const_iterator i (overloads_.begin());
SyntaxErrorException err;
for (; i != i_end; ++i) {
try {
- (**i)(output, arguments);
+ (**i)(output, command);
return;
}
catch (SyntaxErrorException & ex) {
}
prefix_ void senf::console::SimpleCommandOverload::v_execute(std::ostream & os,
- Arguments const & arguments)
+ ParseCommandInfo const & command)
const
{
- fn_(os, arguments);
+ fn_(os, command);
}
///////////////////////////////cc.e////////////////////////////////////////
prefix_ senf::console::CommandOverload::~CommandOverload()
{}
+prefix_ void senf::console::CommandOverload::execute(std::ostream & os,
+ ParseCommandInfo const & command)
+{
+ v_execute(os, command);
+}
+
prefix_ void senf::console::CommandOverload::operator()(std::ostream & os,
- Arguments const & arguments)
+ ParseCommandInfo const & command)
{
- v_execute(os, arguments);
+ execute(os, command);
}
prefix_ void senf::console::CommandOverload::help(std::ostream & os)
// Types
typedef boost::intrusive_ptr<CommandOverload> ptr;
- typedef CommandNode::Arguments Arguments;
///////////////////////////////////////////////////////////////////////////
virtual ~CommandOverload();
- void operator()(std::ostream & os, Arguments const & arguments);
+ void execute(std::ostream & os, ParseCommandInfo const & command);
///< Call the overload
/**< If the \a arguments are not acceptable for this
- overload, a SyntaxErrorException must be thrown. */
+ overload, a SyntaxErrorException must be thrown.
+ Same as operator()() */
+
+ void operator()(std::ostream & os, ParseCommandInfo const & command);
+ ///< Call the overload
+ /**< If the \a arguments are not acceptable for this
+ overload, a SyntaxErrorException must be thrown.
+ Same as execute() */
+
void help(std::ostream & os); ///< Provide help for this specific overload
OverloadedCommandNode & node(); ///< Access owning node
private:
#endif
virtual void v_help(std::ostream & os) const = 0;
- virtual void v_execute(std::ostream & os, Arguments const & arguments) const = 0;
+ virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const = 0;
private:
OverloadedCommandNode * node_;
OverloadedCommandNode();
virtual void v_help(std::ostream & output) const;
- virtual void v_execute(std::ostream & output, Arguments const & arguments) const;
+ virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const;
typedef std::vector<CommandOverload::ptr> Overloads;
/** \brief Basic command overload
This is an implementation of CommandOverload which allows to call an arbitrary callback with
- the correct signature (<tt>void (std::ostream &, Arguments const &)</tt>)
+ the correct signature
+ (<tt>void (std::ostream &, senf::console::ParseCommandInfo const &)</tt>)
*/
class SimpleCommandOverload
: public CommandOverload
// Types
typedef boost::intrusive_ptr<SimpleCommandOverload> ptr;
- typedef boost::function<void (std::ostream &, Arguments const &)> Function;
+ typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
SimpleCommandOverload(Function fn);
virtual void v_help(std::ostream & os) const;
- virtual void v_execute(std::ostream & os, Arguments const & arguments) const;
+ virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const;
Function fn_;
std::string doc_;
namespace {
- void fn1(std::ostream &, senf::console::CommandOverload::Arguments const &)
+ void fn1(std::ostream &, senf::console::ParseCommandInfo const &)
{
throw senf::console::SyntaxErrorException("fn1 error");
}
- void fn2(std::ostream &, senf::console::CommandOverload::Arguments const &)
+ void fn2(std::ostream &, senf::console::ParseCommandInfo const &)
{
throw senf::console::SyntaxErrorException("fn2 error");
}
- void fn3(std::ostream & os, senf::console::CommandOverload::Arguments const &)
+ void fn3(std::ostream & os, senf::console::ParseCommandInfo const &)
{
os << "fn3\n";
}
{
senf::console::ParseCommandInfo info;
std::stringstream ss;
- BOOST_CHECK_THROW( senf::console::root()("overload")(ss, info.arguments()),
+ BOOST_CHECK_THROW( senf::console::root()("overload")(ss, info),
senf::console::SyntaxErrorException );
cmd.add(senf::console::SimpleCommandOverload::create(&fn3)).doc("fn3");
- BOOST_CHECK_NO_THROW( senf::console::root()("overload")(ss, info.arguments()) );
+ BOOST_CHECK_NO_THROW( senf::console::root()("overload")(ss, info) );
BOOST_CHECK_EQUAL( ss.str(), "fn3\n" );
}
}
prefix_ senf::console::DirectoryNode &
+senf::console::ScopedDirectoryBase::getDirectory(std::string const & name)
+ const
+{
+ return node().getDirectory(name);
+}
+
+prefix_ senf::console::DirectoryNode &
senf::console::ScopedDirectoryBase::operator[](std::string const & name)
const
{
}
prefix_ senf::console::CommandNode &
+senf::console::ScopedDirectoryBase::getCommand(std::string const & name)
+ const
+{
+ return node().getCommand(name);
+}
+
+prefix_ senf::console::CommandNode &
senf::console::ScopedDirectoryBase::operator()(std::string const & name)
const
{
template <class Owner>
prefix_ senf::console::SimpleCommandNode & senf::console::
senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
- void (Owner::*fn)(std::ostream & output,
- CommandNode::Arguments const & arguments))
+ void (Owner::*fn)(std::ostream &, ParseCommandInfo const &))
{
return node.add(name, boost::bind(fn,boost::ref(owner),_1,_2));
}
///\{
GenericNode::ptr remove(std::string const & name);
+ DirectoryNode & getDirectory(std::string const & name) const;
DirectoryNode & operator[](std::string const & name) const;
+ CommandNode & getCommand(std::string const & name) const;
CommandNode & operator()(std::string const & name) const;
GenericNode & get(std::string const & name) const;
DirectoryNode & mkdir(std::string const & name);
template <class Owner>
SimpleCommandNode & senf_console_add_node(
- DirectoryNode & node, Owner & owner, std::string const & name,
- void (Owner::*fn)(std::ostream & output, CommandNode::Arguments const & arguments));
+ DirectoryNode & node, Owner & owner, std::string const & name,
+ void (Owner::*fn)(std::ostream &, ParseCommandInfo const &));
template <class Node>
DirectoryNode & senf_console_add_node(
dir.add("member", &Self::member);
}
- void member(std::ostream & os, senf::console::CommandNode::Arguments const &) {
+ void member(std::ostream & os, senf::console::ParseCommandInfo const &) {
os << "member";
}
};
senf::console::root().add("ob",ob.dir);
std::stringstream ss;
senf::console::ParseCommandInfo info;
- senf::console::root()["ob"]("member")(ss, info.arguments());
+ senf::console::root()["ob"]("member")(ss, info);
BOOST_CHECK_EQUAL( ss.str(), "member" );
}
BOOST_CHECK_THROW( senf::console::root()["ob"], senf::console::UnknownNodeNameException );
}
namespace {
- void callback(std::ostream & os, senf::console::CommandNode::Arguments const &) {
+ void callback(std::ostream & os, senf::console::ParseCommandInfo const &) {
os << "cb";
}
}
dir.add("cb", &callback);
std::stringstream ss;
senf::console::ParseCommandInfo info;
- senf::console::root()["dir"]("cb")(ss, info.arguments());
+ senf::console::root()["dir"]("cb")(ss, info);
BOOST_CHECK_EQUAL( ss.str(), "cb" );
}
BOOST_CHECK_THROW( senf::console::root()["dir"],
lastCommand_ = data;
try {
- if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1,
- boost::ref(out_t::member))))
+ if (! parser_.parse(data, boost::bind<void>( boost::ref(executor_),
+ boost::ref(out_t::member),
+ _1 )) )
out_t::member << "syntax error" << std::endl;
}
catch (Executor::ExitException &) {
namespace {
- void fn(std::ostream & output,
- senf::console::CommandNode::Arguments const & arguments) {
- senf::console::CommandNode::Arguments::iterator i (arguments.begin());
- senf::console::CommandNode::Arguments::iterator i_end (arguments.end());
+ void fn(std::ostream & output, senf::console::ParseCommandInfo const & command) {
+ senf::console::CommandNode::Arguments::iterator i (command.arguments().begin());
+ senf::console::CommandNode::Arguments::iterator i_end (command.arguments().end());
for (; i != i_end; ++i) {
- senf::console::CommandNode::Arguments::value_type::iterator j (i->begin());
- senf::console::CommandNode::Arguments::value_type::iterator j_end (i->end());
+ senf::console::ParseCommandInfo::ArgumentsRange::value_type::iterator j (i->begin());
+ senf::console::ParseCommandInfo::ArgumentsRange::value_type::iterator j_end (i->end());
for (; j != j_end; ++j)
output << j->value() << ' ';
}
.doc("Example of a member function");
}
- void blub(std::ostream & output, senf::console::CommandNode::Arguments const & args) {
+ void blub(std::ostream & output, senf::console::ParseCommandInfo const &) {
output << "blub\n";
}
};
- void shutdownServer(std::ostream &,
- senf::console::CommandNode::Arguments const &)
+ void shutdownServer(std::ostream &, senf::console::ParseCommandInfo const &)
{
senf::Scheduler::instance().terminate();
throw senf::console::Executor::ExitException();
configuration, described in this documentation.
\see \ref senf_build \n
+ \ref senf_setup \n
\ref senf_components \n
- \ref senf_svnsetup \n
\ref senf_overview
\section senf_preliminaries Preliminaries
which relies on \c epoll)
*/
-/** \page senf_build Building the framework
+/** \page senf_build Building the SENF framework
This procedure will test building the complete framework including the unit tests and the
Sniffer test application. This build is \e not needed to use the framework since every project
After you have successfully built the library tests, you can continue to setup your own project
using SENF.
- \see \ref senf_components \n
- \ref senf_svnsetup
+ \see \ref senf_setup \n
+ \ref senf_components \n
+ \ref senf_overview
\section senf_checkout Getting the code
</pre>
This will create a new directory \c senf within the current directory. For further documentation
- on the use of Subversion, see the \c svn manpage or the subversion homepage at
+ on the use of Subversion, see the \c svn man-page or the subversion homepage at
http://subversion.tigris.org. A very good introduction and reference to subversion is available
at http://svnbook.red-bean.com.
are just arbitrary examples).
*/
+/** \page senf_setup Setting up a new project using SENF
+
+ The most simple way to use SENF for now is to checkout the svn repository and build SENF
+ yourselves. After you have built SENF, reference your SENF build directory from your build
+ environment. The most flexible way to do this, is to use a symbolic link to your SENF build.
+
+ Here an example \c SConstruct file for a project using SENF. This script expects SENF to be
+ found in the <tt>%senf</tt> sub-directory of the directory, where the \c SConstruct file is
+ found. This may either be a SENF checkout (if managing your project via subversion, you can use
+ <tt>svn:externals</tt> for this) or a symbolic link to your SENF checkout.
+
+ \code
+ import os.path, glob
+
+ env = Environment(
+
+ LIBS = [ 'senf', 'iberty', 'boost_regex', 'boost_iostreams' ],
+ CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ],
+
+ )
+
+ # If we have a symbolic link 'senf' pointing to our own senf build, use it (and assume
+ # it's in debug mode)
+ if os.path.exists('senf'):
+ print "\nUsing SENF in 'senf'\n"
+ env.Append(
+
+ CPPDEFINES = [ 'SENF_DEBUG' ],
+ LIBPATH = [ 'senf' ],
+ CPPPATH = [ 'senf/include' ],
+ CXXFLAGS = [ '-O0', '-g', '-fno-inline' ],
+ LINKFLAGS = [ '-g', '-rdynamic' ],
+
+ )
+ env.Execute([ 'scons -C senf libsenf.a' ])
+ else:
+ print "\nUsing system installed SENF\n"
+
+ # replace 'mytarget' with the name of your target executable
+ env.Program(
+ target = 'mytarget',
+ source = glob.glob('*.cc'),
+ );
+ \endcode
+
+ This script automatically set's up the build correctly when using a self-compiled SENF in debug
+ mode (which is the default mode):
+ \li It links in all the required libraries in the correct order: First \c libsenf, then the
+ other needed libraries \c liberty, \c libboost_regex and \c libboost_iostreams.
+ \li It defines the <tt>SENF_DEBUG</tt> preprocessor symbol correctly
+ \li It correctly sets the include and library path
+ \li It adds sensible debug flags
+ \li It adds <tt>-rdynamic</tt> to the link command. This is needed to get a nice backtrace from
+ exceptions.
+ \li It automatically rebuilds SENF if needed
+
+ \see \ref senf_components \n
+ \ref senf_overview
+ */
+
/** \page senf_components The SENF modules
The framework is made up of several modular components. When using the library, it is possible
to selectively choose to use only a subset of the implemented modules.
- \see \ref senf_build \n
- \ref senf_svnsetup
+ \see \ref senf_overview
\section libPPI libPPI: Packet Processing Infrastructure
\see <a href="../../senfscons/doc/html/index.html">SENFSCons reference</a>
*/
-/** \page senf_svnsetup Setting up a new project using SENF
-
- The preferred way to use SENF in a new project is to rely on Subversion and make use of the
- SENFSCons build environment. The following sections will describe, how this setup works.
-
- \see \ref senf_build \n
- \ref senf_components \n
- \ref senf_overview
-
- \section svnext Setting up the project repository
-
- The most seamless integration is possible if you rely on Subversion to manage the new
- project. Subversion does support 'external repositories'. This allows to import code from a
- foreign repository into the checkout without importing it into your repository. The code will
- always stay at the remote repository, updates are automatically available.
-
- First setup a new empty repository as described for example in the Subversion book at
- http://svnbook.red-bean.com or as mandated by your site policy. We will call the project 'Foo'
- and assume, that the project has been checked out into the 'Foo' directory.
-
- You now have to decide, which modules you want to use. Every module resides in it's own
- subdirectory in the SENF repository. Instead of directly checking out the code, we will use \c
- svn:externals. This will instruct \c svn to automatically check out the needed directories from
- the BerliOS SENF repository. Change to the 'Foo' directory and type
-
- <pre>
- $ svn propedit svn:externals .
- </pre>
-
- The default editor (probably VI) will be started with the current value of the svn:externals
- property (which will probably be empty). Now add all the modules you want plus \c senfscons and
- possibly \c doclib (if you want to build the documentation). You will almost certainly need the
- \c Utils module, since all other modules depend on it.
-
- For example, if you want to use the \c Scheduler and \c Socket module, the file will look like
-
- <pre>
- senfscons http://svn.berlios.de/svnroot/repos/senf/trunk/senfscons
- Utils http://svn.berlios.de/svnroot/repos/senf/trunk/Utils
- Scheduler http://svn.berlios.de/svnroot/repos/senf/trunk/Scheduler
- Socket http://svn.berlios.de/svnroot/repos/senf/trunk/Socket
- </pre>
-
- exit the editor and the property will be set. Now run
-
- <pre>
- $ svn update
- </pre>
-
- and the code will be checked out into the corresponding directories.
-
- \section senf_new_conf Configuring SENFSCons
-
- To set up the build environment, copy the <tt>senfscons/SConstruct.template</tt> to
- <tt>SConstruct</tt> in the project root. The default setup of this file is to build all
- subdirectories (using the \c SConscript files of the subdirectories). You can add additional
- global targets and configuration parameters here.
-
- If you want to use a non-default compiler or the boost library is not installed in the system
- directories, you will have to copy <tt>senfscons/SConfig.template</tt> to <tt>SConfig</tt> in
- the project root and edit it there. You should \e never add \c SConfig to the repository since
- it should only contain local settings necessary for building on your local system. You should
- therefore add \c SConfig to the list of files ignored by Subversion in the project root. In the
- project root execute
-
- <pre>
- $ svn propedit svn:ignore .
- </pre>
-
- and add \c SConfig as a new line to the property.
-
- \section new_build Building the project
-
- You should now be able to build your project using
-
- <pre>
- $ scons
- </pre>
-
- If you have not changed the \c SConstruct file, this will build all modules you have imported
- into your project. To build and execute the unit tests, use
-
- <pre>
- $ scons all_tests
- </pre>
-
- you can also build only a subdirectory by changing to it and running
-
- <pre>
- $ scons -u [target]
- </pre>
-
- \see <a href="../../senfscons/doc/html/index.html">SENFSCons reference</a> \n
- <a href="http://www.scons.org/documentation.php">SCons documentation</a> \n
- <a href="http://svnbook.red-bean.com">Subversion online book</a> \n
- <a href="http://subversion.tigris.org">Subversion Homepage</a>
- */
-
/** \page senf_overview Introduction to the framework
The SENF framework is relatively complex and makes use of advanced features of the C++
\see <a href="../../Examples/doc/html/index.html">Examples</a> \n
\ref senf_components \n
- \ref senf_svnsetup \n
- \ref senf_build
+ \ref senf_setup
\section senf_conventions Coding Conventions
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
+// compile-command: "scons doc"
// mode: flyspell
// mode: auto-fill
// End:
It is possible to connect two active or passive connectors with each other using a special
adaptor module (senf::ppi::module::PassiveQueue or senf::ppi::module::ActiveFeeder
respectively).
+
+ Additionally, the connectors must be type-compatible: Either one (or both) of the connectors
+ must be untyped (they accept arbitrary senf::Packet's, the optional tempalte argument is empty),
+ or they both accept the same type of packet. This check is performed at runtime.
To complete our simplified example: Lets connet senf::ppi::module::ActiveSocketReader and
senf::ppi::module::PassiveSocketWriter to our example module:
as \a source argument. In the same way, if a module has an input connector called \c input,
the module may be given directly as \a target argument. This simplifies the most common case
of a module with one input and one output connector.
+
+ The connect call will check at runtime, whether the two connectors are type-compatible:
+ \li Either or both of the connectors are untyped (they accept/send arbitrary senf::Packet's)
+ \li Both connectors send/accept the exactly same packet type.
+
+ \throws IncompatibleConnectorsException if the two connectors are not type compatible.
\see \ref ppi_connections
*/
\todo Fix the file support to use threads (?) fork (?) and a pipe so it works reliably even
over e.g. NFS.
+
+ \todo Add a check in the alarm callback which is already called every x seconds to check,
+ that a single callback is not blocking.
*/
class Scheduler
: boost::noncopyable
#include <execinfo.h>
#include <sstream>
#include "../config.hh"
+
+// Copied from the binutils sources
+#define HAVE_DECL_BASENAME 1
+#define HAVE_DECL_ASPRINTF 1
+#define HAVE_DECL_VASPRINTF 1
#include "impl/demangle.h"
#define prefix_
// ...
}
catch (senf::ExceptionMixin & e) {
- e << boost::format("\ncall id 0x%04x@%s") % id % address;
+ e << boost::format("\n" "call id 0x%04x@%s") % id % address;
}
\endcode
the GNU-libc.
To apply these features (extensibility, backtrace) to a non-senf exception, the non-senf
- exception can be wrapped and rethrown.
+ exception can be wrapped and re-thrown.
\code
void foo() {
try {
foo();
}
catch (senf::ExceptionMixin & ex) {
- ex << "\nadd this info";
+ ex << "\n" "add this info";
}
}
catch (std::bad_cast const & ex) {
\todo Link against libcwd to add file-name/line-number information to the backtrace and remove
the dependency on -rdynamic
+ \todo Or better, use addr2line to obtain that information when showing the backtrace when
+ catched within Daemon (<tt>addr2line -fsiCe argv[0]</tt>)
+ \todo Add signal handlers for the bad signals which writes a backtrace to stderr and
+ terminates. This should probably write out a raw backtrace without de-mangling or
+ line-numbers since we don't want to mess with dynamic memory when the heap might be
+ corrupted ... Another handler for e.g. SIGUSR2 is nice to show a debug backtrace on demand
*/
namespace senf {
// compile-command: "scons -u test"
// comment-column: 40
// End:
+
// Custom includes
#include "malloc.h"
+
+// Copied from the binutils sources
#define HAVE_DECL_BASENAME 1
#define HAVE_DECL_ASPRINTF 1
#define HAVE_DECL_VASPRINTF 1
autoThrottling
autotoc
aVectorCollection
+backtrace
+BaseException
BaseParser
berlios
+BerliOS
bitfield
bool
bund
ClientSocketHandle
CloneSource
cmd
+com
CommandNode
CommandOverload
CommandParser
DataPacket
dd
de
+DEBUGINFO
DebugModules
decapsulated
DefaultArea
defaultInit
defgroup
deque
+dia
dil
dir
DirectoryNode
enableChecksum
endcode
endif
+endl
+ENOFILE
enum
eof
EPIPE
+epoll
errno
ErrnoException
ErrorException
+errorNumber
eth
ethernet
EthernetPacket
ExampleListPolicy
ExampleVariantPolicy
ExampleVectorPolicy
+EXC
+ExceptionMixin
ExtendedParser
FFFF
FileBody
flurgle
fokus
foo
+fooCallback
+FooException
FooParser
ForwardingRoute
+ForwardRange
fraunhofer
FroblizerArea
+fsiCe
+gcc
+GenericNode
+getCommand
+getDirectory
GlobalScope
GlobalTestArea
+graphviz
gre
GREPacket
GREPacketParser
join
key
li
+libc
+libcwd
libPacket
libPackets
LinkScope
multicast
mycommand
mydir
+myDirectory
MyList
+MyNodeType
MyParser
myserver
+MySpecialObject
MyVariant
MyVariantPolicy
MyVector
NIS
NoAddressingPolicy
NoBuiltin
+NodeCreateTraits
noinit
noroute
nothrow
+ob
ObjectDirectory
offene
Ok
PassiveSource
png
POPD
+POSIX
ppi
pre
prev
protocolbundle
protocolbundles
protocolType
+ptr
PUSHD
py
QueueingDiscipline
ratestuffer
RawINetProtocol
RawV
+rdynamic
refcount
registerEvent
registerPacket
registerPacketType
registerSomePacket
RegistrationProxy
+repos
rerference
rfc
RO
SafePacketParser
SatCom
Satelitenkommunikation
+SConfig
scons
+SCons
+ScopedDirectory
ScopeId
screenshot
sec
seekable
senf
senfscons
+SENFSCons
ServerLog
serverlog
ServerSocketHandle
setfill
setFromPosition
setw
+SIGUSR
SimpleCommandNode
SimpleCommandOverload
SimplePacketType
SomeEvent
SomeEventArg
someField
+somelib
SomeModule
someOtherField
SomePacket
someServer
SomeTag
someVector
+sourceforge
src
ssi
std
+stderr
stefan
STL
strerror
struct
structors
+svn
+svnbook
+svnroot
SyntaxErrorException
SyntaxException
SystemException
templated
ThresholdQueueing
ThrottleBarrier
+tigris
todo
tr
TruncatedPacketException
UIntFieldParser
Unhandled
unicast
+uniquified
+UnknownNodeNameException
unthrottle
unthrottled
unthrottles
vlanId
VLanId
VoidPacketParser
+WrapException
www
+xmlsoft
+XSLT
+xsltproc
xxxx
xxxxxx
xyz