From: g0dil Date: Thu, 3 Apr 2008 12:54:06 +0000 (+0000) Subject: PPI: Add senf::connect() packet type compatibility check documentation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=be33ff96c5b89738694da272d8610564cce48bfb;p=senf.git PPI: Add senf::connect() packet type compatibility check documentation Console: Pass ParseCommandInfo instead of ArgumentsRange to the callbacks Console: Add named aliases for operator overloads ('[]' and '()') Utils: Document, where impl/demangle.h comes from Updated the 'Setting up a new project using SENF' documentation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@777 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Console/Executor.cc b/Console/Executor.cc index 517c46c..5e4b6f2 100644 --- a/Console/Executor.cc +++ b/Console/Executor.cc @@ -46,8 +46,8 @@ namespace { /////////////////////////////////////////////////////////////////////////// // 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 )); @@ -57,7 +57,7 @@ prefix_ void senf::console::Executor::operator()(ParseCommandInfo const & comman try { switch(command.builtin()) { case ParseCommandInfo::NoBuiltin : - traverseCommand(command.commandPath())(output, command.arguments()); + traverseCommand(command.commandPath())(output, command); break; case ParseCommandInfo::BuiltinCD : diff --git a/Console/Executor.cci b/Console/Executor.cci index 3126fa1..81ef6e0 100644 --- a/Console/Executor.cci +++ b/Console/Executor.cci @@ -39,6 +39,12 @@ prefix_ senf::console::Executor::Executor() 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 { diff --git a/Console/Executor.hh b/Console/Executor.hh index 48d62ba..81dafd9 100644 --- a/Console/Executor.hh +++ b/Console/Executor.hh @@ -63,8 +63,6 @@ namespace console { /////////////////////////////////////////////////////////////////////////// // Types - typedef boost::iterator_range< ParseCommandInfo::argument_iterator> Arguments; - /// Thrown by built-in 'exit' command struct ExitException {}; @@ -77,9 +75,15 @@ namespace console { ///\} /////////////////////////////////////////////////////////////////////////// - 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: diff --git a/Console/Executor.test.cc b/Console/Executor.test.cc index 902bc84..a507571 100644 --- a/Console/Executor.test.cc +++ b/Console/Executor.test.cc @@ -42,7 +42,7 @@ namespace { 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"; } } @@ -60,7 +60,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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(), "" ); @@ -69,7 +69,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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(), "" ); @@ -78,7 +78,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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" ); @@ -87,7 +87,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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(), "" ); @@ -96,7 +96,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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" ); } @@ -104,7 +104,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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" ); } @@ -112,7 +112,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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" ); } @@ -120,7 +120,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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(), "" ); @@ -128,7 +128,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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(), "" ); @@ -138,14 +138,14 @@ BOOST_AUTO_UNIT_TEST(executor) 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" ); } @@ -153,7 +153,7 @@ BOOST_AUTO_UNIT_TEST(executor) { 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" ); } diff --git a/Console/Mainpage.dox b/Console/Mainpage.dox index 50cc0e7..9c0ea9a 100644 --- a/Console/Mainpage.dox +++ b/Console/Mainpage.dox @@ -50,7 +50,7 @@ \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"; diff --git a/Console/Node.cc b/Console/Node.cc index 1cd8d40..4886b77 100644 --- a/Console/Node.cc +++ b/Console/Node.cc @@ -135,10 +135,10 @@ prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output) } 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//////////////////////////////////////// diff --git a/Console/Node.cci b/Console/Node.cci index c5adaf3..ed1e30e 100644 --- a/Console/Node.cci +++ b/Console/Node.cci @@ -93,7 +93,7 @@ prefix_ senf::console::DirectoryNode::ptr senf::console::DirectoryNode::create() } prefix_ senf::console::DirectoryNode & -senf::console::DirectoryNode::operator[](std::string const & name) +senf::console::DirectoryNode::getDirectory(std::string const & name) const { try { @@ -102,8 +102,15 @@ senf::console::DirectoryNode::operator[](std::string const & name) 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 { @@ -112,6 +119,13 @@ senf::console::DirectoryNode::operator()(std::string const & name) 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) { @@ -169,11 +183,18 @@ prefix_ senf::console::CommandNode::cptr senf::console::CommandNode::thisptr() 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); } /////////////////////////////////////////////////////////////////////////// diff --git a/Console/Node.hh b/Console/Node.hh index 961a1b8..86c3e17 100644 --- a/Console/Node.hh +++ b/Console/Node.hh @@ -38,7 +38,7 @@ \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"; @@ -61,7 +61,7 @@ .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) { // ... } @@ -123,7 +123,7 @@ 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 @@ -132,8 +132,9 @@ 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. @@ -142,7 +143,7 @@ \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 @@ -168,11 +169,14 @@ 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 @@ -407,24 +411,42 @@ namespace console { 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 @@ -439,7 +461,7 @@ namespace console { template GenericNode & traverse(ForwardRange const & range); ///< Traverse node path starting at this node - /**< The FordwareRange::value_type must be + /**< The ForwardRange::value_type must be (convertible to) std::string. Each range element constitutes a step along the node traversal. @@ -491,8 +513,7 @@ namespace console { 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 */ @@ -507,13 +528,20 @@ namespace console { typedef boost::shared_ptr cptr; typedef boost::weak_ptr 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. */ @@ -527,7 +555,7 @@ namespace console { #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 @@ -537,8 +565,6 @@ namespace console { private: }; - typedef CommandNode::Arguments Arguments; - /** \brief Most simple CommandNode implementation This CommandNode implementation simply forwards the \a output and \a arguments arguments to @@ -557,7 +583,7 @@ namespace console { typedef boost::shared_ptr cptr; typedef boost::weak_ptr weak_ptr; - typedef boost::function Function; + typedef boost::function Function; /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -578,7 +604,7 @@ namespace console { 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_; diff --git a/Console/Node.test.cc b/Console/Node.test.cc index f5a2c02..d2f9142 100644 --- a/Console/Node.test.cc +++ b/Console/Node.test.cc @@ -60,7 +60,7 @@ BOOST_AUTO_UNIT_TEST(gnericNode) } namespace { - void callback(std::ostream & os, senf::console::SimpleCommandNode::Arguments arguments) + void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { os << "callback"; } @@ -118,8 +118,7 @@ BOOST_AUTO_UNIT_TEST(directoryNode) namespace { struct Functor { - void operator()(std::ostream & os, - senf::console::SimpleCommandNode::Arguments const &) { + void operator()(std::ostream & os, senf::console::ParseCommandInfo const &) { os << "functor"; } }; @@ -134,13 +133,13 @@ BOOST_AUTO_UNIT_TEST(senfConsoleAddNode) { 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" ); } @@ -155,7 +154,7 @@ BOOST_AUTO_UNIT_TEST(simpleCommandNode) { 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" ); } diff --git a/Console/OverloadedCommand.cc b/Console/OverloadedCommand.cc index 30e7fbb..5edbd20 100644 --- a/Console/OverloadedCommand.cc +++ b/Console/OverloadedCommand.cc @@ -48,7 +48,7 @@ prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os) } prefix_ void senf::console::OverloadedCommandNode::v_execute(std::ostream & output, - Arguments const & arguments) + ParseCommandInfo const & command) const { Overloads::const_iterator i (overloads_.begin()); @@ -56,7 +56,7 @@ prefix_ void senf::console::OverloadedCommandNode::v_execute(std::ostream & outp SyntaxErrorException err; for (; i != i_end; ++i) { try { - (**i)(output, arguments); + (**i)(output, command); return; } catch (SyntaxErrorException & ex) { @@ -76,10 +76,10 @@ prefix_ void senf::console::SimpleCommandOverload::v_help(std::ostream & os) } 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//////////////////////////////////////// diff --git a/Console/OverloadedCommand.cci b/Console/OverloadedCommand.cci index ea87c2d..6fc076d 100644 --- a/Console/OverloadedCommand.cci +++ b/Console/OverloadedCommand.cci @@ -36,10 +36,16 @@ 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) diff --git a/Console/OverloadedCommand.hh b/Console/OverloadedCommand.hh index e1481e5..a967120 100644 --- a/Console/OverloadedCommand.hh +++ b/Console/OverloadedCommand.hh @@ -52,16 +52,23 @@ namespace console { // Types typedef boost::intrusive_ptr 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 @@ -75,7 +82,7 @@ namespace console { 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_; @@ -142,7 +149,7 @@ namespace console { 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 Overloads; @@ -153,7 +160,8 @@ namespace console { /** \brief Basic command overload This is an implementation of CommandOverload which allows to call an arbitrary callback with - the correct signature (void (std::ostream &, Arguments const &)) + the correct signature + (void (std::ostream &, senf::console::ParseCommandInfo const &)) */ class SimpleCommandOverload : public CommandOverload @@ -163,7 +171,7 @@ namespace console { // Types typedef boost::intrusive_ptr ptr; - typedef boost::function Function; + typedef boost::function Function; /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -185,7 +193,7 @@ namespace console { 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_; diff --git a/Console/OverloadedCommand.test.cc b/Console/OverloadedCommand.test.cc index ece3da8..184c3ba 100644 --- a/Console/OverloadedCommand.test.cc +++ b/Console/OverloadedCommand.test.cc @@ -38,17 +38,17 @@ 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"; } @@ -67,11 +67,11 @@ BOOST_AUTO_UNIT_TEST(overladedCommand) { 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" ); } diff --git a/Console/ScopedDirectory.cci b/Console/ScopedDirectory.cci index b6acd78..518a3af 100644 --- a/Console/ScopedDirectory.cci +++ b/Console/ScopedDirectory.cci @@ -46,6 +46,13 @@ senf::console::ScopedDirectoryBase::remove(std::string const & name) } 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 { @@ -53,6 +60,13 @@ senf::console::ScopedDirectoryBase::operator[](std::string const & name) } 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 { diff --git a/Console/ScopedDirectory.cti b/Console/ScopedDirectory.cti index 87ce190..d1fbe7a 100644 --- a/Console/ScopedDirectory.cti +++ b/Console/ScopedDirectory.cti @@ -73,8 +73,7 @@ senf_console_add_node(DirectoryNode & node, Owner & , std::string const & name, template 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)); } diff --git a/Console/ScopedDirectory.hh b/Console/ScopedDirectory.hh index cec50db..6c27f40 100644 --- a/Console/ScopedDirectory.hh +++ b/Console/ScopedDirectory.hh @@ -72,7 +72,9 @@ namespace console { ///\{ 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); @@ -173,8 +175,8 @@ namespace console { template 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 DirectoryNode & senf_console_add_node( diff --git a/Console/ScopedDirectory.test.cc b/Console/ScopedDirectory.test.cc index 4a3ce75..0345c21 100644 --- a/Console/ScopedDirectory.test.cc +++ b/Console/ScopedDirectory.test.cc @@ -46,7 +46,7 @@ namespace { 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"; } }; @@ -59,14 +59,14 @@ BOOST_AUTO_UNIT_TEST(scopedDirectory) 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"; } } @@ -79,7 +79,7 @@ BOOST_AUTO_UNIT_TEST(scopedDirectoryVoid) 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"], diff --git a/Console/Server.cc b/Console/Server.cc index 4d6eb2a..856a67c 100644 --- a/Console/Server.cc +++ b/Console/Server.cc @@ -171,8 +171,9 @@ prefix_ void senf::console::Client::clientData(ReadHelper::ptr hel lastCommand_ = data; try { - if (! parser_.parse(data, boost::bind(boost::ref(executor_), _1, - boost::ref(out_t::member)))) + if (! parser_.parse(data, boost::bind( boost::ref(executor_), + boost::ref(out_t::member), + _1 )) ) out_t::member << "syntax error" << std::endl; } catch (Executor::ExitException &) { diff --git a/Console/testServer.cc b/Console/testServer.cc index b7d5124..b62554d 100644 --- a/Console/testServer.cc +++ b/Console/testServer.cc @@ -40,13 +40,12 @@ 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() << ' '; } @@ -62,13 +61,12 @@ namespace { .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(); diff --git a/Mainpage.dox b/Mainpage.dox index a74b1dd..7aa5ca3 100644 --- a/Mainpage.dox +++ b/Mainpage.dox @@ -60,8 +60,8 @@ 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 @@ -86,7 +86,7 @@ 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 @@ -95,8 +95,9 @@ 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 @@ -108,7 +109,7 @@ 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. @@ -128,13 +129,72 @@ 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 %senf 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 + svn:externals 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 SENF_DEBUG preprocessor symbol correctly + \li It correctly sets the include and library path + \li It adds sensible debug flags + \li It adds -rdynamic 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 @@ -193,104 +253,6 @@ \see SENFSCons reference */ -/** \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 - -
-    $ svn propedit svn:externals .
-    
- - 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 - -
-    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
-    
- - exit the editor and the property will be set. Now run - -
-    $ svn update
-    
- - 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 senfscons/SConstruct.template to - SConstruct 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 senfscons/SConfig.template to SConfig 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 - -
-    $ svn propedit svn:ignore .
-    
- - 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 - -
-    $ scons
-    
- - 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 - -
-    $ scons all_tests
-    
- - you can also build only a subdirectory by changing to it and running - -
-    $ scons -u [target]
-    
- - \see SENFSCons reference \n - SCons documentation \n - Subversion online book \n - Subversion Homepage - */ - /** \page senf_overview Introduction to the framework The SENF framework is relatively complex and makes use of advanced features of the C++ @@ -333,8 +295,7 @@ \see Examples \n \ref senf_components \n - \ref senf_svnsetup \n - \ref senf_build + \ref senf_setup \section senf_conventions Coding Conventions @@ -446,6 +407,7 @@ // c-file-style: "senf" // indent-tabs-mode: nil // ispell-local-dictionary: "american" +// compile-command: "scons doc" // mode: flyspell // mode: auto-fill // End: diff --git a/PPI/Mainpage.dox b/PPI/Mainpage.dox index f2f2905..5afa6e0 100644 --- a/PPI/Mainpage.dox +++ b/PPI/Mainpage.dox @@ -216,6 +216,10 @@ 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: diff --git a/PPI/Setup.hh b/PPI/Setup.hh index cbff044..c113e91 100644 --- a/PPI/Setup.hh +++ b/PPI/Setup.hh @@ -47,6 +47,12 @@ namespace ppi { 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 */ diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 89e91f8..0d51c35 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -160,6 +160,9 @@ namespace senf { \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 diff --git a/Utils/Exception.cc b/Utils/Exception.cc index 4c74f6c..a651239 100644 --- a/Utils/Exception.cc +++ b/Utils/Exception.cc @@ -30,6 +30,11 @@ #include #include #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_ diff --git a/Utils/Exception.hh b/Utils/Exception.hh index 840379e..7abf26c 100644 --- a/Utils/Exception.hh +++ b/Utils/Exception.hh @@ -66,7 +66,7 @@ // ... } 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 @@ -87,7 +87,7 @@ 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 { @@ -106,7 +106,7 @@ foo(); } catch (senf::ExceptionMixin & ex) { - ex << "\nadd this info"; + ex << "\n" "add this info"; } } catch (std::bad_cast const & ex) { @@ -120,6 +120,12 @@ \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 (addr2line -fsiCe argv[0]) + \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 { @@ -322,3 +328,4 @@ namespace senf { // compile-command: "scons -u test" // comment-column: 40 // End: + diff --git a/Utils/TypeInfo.cc b/Utils/TypeInfo.cc index 0effd19..1c18256 100644 --- a/Utils/TypeInfo.cc +++ b/Utils/TypeInfo.cc @@ -28,6 +28,8 @@ // 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 diff --git a/senf.dict b/senf.dict index 19e7576..d04b5c3 100644 --- a/senf.dict +++ b/senf.dict @@ -28,8 +28,11 @@ Augustin autoThrottling autotoc aVectorCollection +backtrace +BaseException BaseParser berlios +BerliOS bitfield bool bund @@ -48,6 +51,7 @@ CIDR ClientSocketHandle CloneSource cmd +com CommandNode CommandOverload CommandParser @@ -66,6 +70,7 @@ DatagramSection DataPacket dd de +DEBUGINFO DebugModules decapsulated DefaultArea @@ -73,6 +78,7 @@ DefaultBundle defaultInit defgroup deque +dia dil dir DirectoryNode @@ -89,12 +95,16 @@ ElementParser enableChecksum endcode endif +endl +ENOFILE enum eof EPIPE +epoll errno ErrnoException ErrorException +errorNumber eth ethernet EthernetPacket @@ -116,6 +126,8 @@ EventType ExampleListPolicy ExampleVariantPolicy ExampleVectorPolicy +EXC +ExceptionMixin ExtendedParser FFFF FileBody @@ -129,12 +141,21 @@ fixvariant flurgle fokus foo +fooCallback +FooException FooParser ForwardingRoute +ForwardRange fraunhofer FroblizerArea +fsiCe +gcc +GenericNode +getCommand +getDirectory GlobalScope GlobalTestArea +graphviz gre GREPacket GREPacketParser @@ -194,6 +215,8 @@ jens join key li +libc +libcwd libPacket libPackets LinkScope @@ -212,9 +235,12 @@ MPEGDVBBundle multicast mycommand mydir +myDirectory MyList +MyNodeType MyParser myserver +MySpecialObject MyVariant MyVariantPolicy MyVector @@ -231,9 +257,11 @@ nextPacketType NIS NoAddressingPolicy NoBuiltin +NodeCreateTraits noinit noroute nothrow +ob ObjectDirectory offene Ok @@ -298,6 +326,7 @@ PassiveSocketWriter PassiveSource png POPD +POSIX ppi pre prev @@ -305,6 +334,7 @@ PriorityJoin protocolbundle protocolbundles protocolType +ptr PUSHD py QueueingDiscipline @@ -316,12 +346,14 @@ RateStuffer ratestuffer RawINetProtocol RawV +rdynamic refcount registerEvent registerPacket registerPacketType registerSomePacket RegistrationProxy +repos rerference rfc RO @@ -329,13 +361,17 @@ RP SafePacketParser SatCom Satelitenkommunikation +SConfig scons +SCons +ScopedDirectory ScopeId screenshot sec seekable senf senfscons +SENFSCons ServerLog serverlog ServerSocketHandle @@ -344,6 +380,7 @@ setEnd setfill setFromPosition setw +SIGUSR SimpleCommandNode SimpleCommandOverload SimplePacketType @@ -359,6 +396,7 @@ someClass SomeEvent SomeEventArg someField +somelib SomeModule someOtherField SomePacket @@ -370,14 +408,19 @@ someserver someServer SomeTag someVector +sourceforge src ssi std +stderr stefan STL strerror struct structors +svn +svnbook +svnroot SyntaxErrorException SyntaxException SystemException @@ -386,6 +429,7 @@ td templated ThresholdQueueing ThrottleBarrier +tigris todo tr TruncatedPacketException @@ -404,6 +448,8 @@ UIntField UIntFieldParser Unhandled unicast +uniquified +UnknownNodeNameException unthrottle unthrottled unthrottles @@ -415,7 +461,11 @@ Ver vlanId VLanId VoidPacketParser +WrapException www +xmlsoft +XSLT +xsltproc xxxx xxxxxx xyz