--- /dev/null
+@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global"
+
+PROJECT_NAME = libConsole
+GENERATE_TAGFILE = doc/Console.tag
+ALPHABETICAL_INDEX = NO
+
+TAGFILES = \
+ "$(TOPDIR)/Socket/doc/Socket.tag" \
+ "$(TOPDIR)/Scheduler/doc/Scheduler.tag" \
+ "$(TOPDIR)/Utils/doc/Utils.tag"
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \mainpage The Configuration and Runtime Control Framework
+
+ The Console library implements a runtime interactive (network) console which allows to
+ configure, control and manipulate a running application in any way. Additionally this library
+ provides support for configuration files and command line parsing which can be used with or
+ without the network console.
+ */
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// mode: flyspell
+// mode: auto-fill
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Node non-inline non-template implementation */
+
+#include "Node.hh"
+//#include "Node.ih"
+
+// Custom includes
+
+//#include "Node.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+//senf::console::DirectoryNode
+
+prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node, bool uniquify)
+{
+ if (children_.find(node->name()) != children_.end()) {
+ if (! uniquify)
+ throw DuplicateNodeNameException() << ": '" << node->name() << "'";
+ unsigned suffix (0);
+ std::string newName;
+ do {
+ ++suffix;
+ newName = node->name() + boost::lexical_cast<std::string>(suffix);
+ } while (children_.find(newName) != children_.end());
+ name(*node, newName);
+ }
+ children_.insert(std::make_pair(node->name(),node));
+}
+
+prefix_ senf::console::GenericNode &
+senf::console::DirectoryNode::lookup(std::string const & name)
+ const
+{
+ ChildMap::const_iterator i (children_.find(name));
+ if (i == children_.end())
+ throw UnknownNodeNameException() << ": '" << name << "'";
+ return *(i->second);
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Node.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Node inline non-template implementation */
+
+//#include "Node.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::GenericNode
+
+prefix_ std::string const & senf::console::GenericNode::name()
+ const
+{
+ return name_;
+}
+
+prefix_ senf::console::GenericNode::GenericNode(std::string const & name, bool managed)
+ : name_ (name), managed_ (managed)
+{}
+
+prefix_ void senf::console::GenericNode::name(std::string const & name)
+{
+ name_ = name;
+}
+
+prefix_ void senf::console::GenericNode::name(GenericNode & node, std::string const & name)
+{
+ node.name_ = name;
+}
+
+prefix_ senf::console::DirectoryNode & senf::console::GenericNode::parent()
+ const
+{
+ SENF_ASSERT( parent_ );
+ return *parent_;
+}
+
+prefix_ bool senf::console::GenericNode::managed()
+ const
+{
+ return managed_;
+}
+
+prefix_ bool senf::console::GenericNode::release()
+{
+ // Beware ! call release() first so the call is not short-circuited way !
+ return intrusive_refcount_base::release() && managed_;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::DirectoryNode
+
+prefix_ void senf::console::DirectoryNode::add(std::auto_ptr<GenericNode> node, bool uniquify)
+{
+ SENF_ASSERT( node->managed() );
+ add(GenericNode::ptr(node.release()), uniquify);
+}
+
+prefix_ void senf::console::DirectoryNode::add(GenericNode & node, bool uniquify)
+{
+ SENF_ASSERT( ! node.managed() );
+ add(GenericNode::ptr(&node),uniquify);
+}
+
+prefix_ senf::console::DirectoryNode &
+senf::console::DirectoryNode::operator[](std::string const & name)
+ const
+{
+ return dynamic_cast<DirectoryNode&>(lookup(name));
+}
+
+prefix_ senf::console::CommandNode &
+senf::console::DirectoryNode::operator()(std::string const & name)
+ const
+{
+ return dynamic_cast<CommandNode&>(lookup(name));
+}
+
+prefix_ senf::console::DirectoryNode::DirectoryNode(std::string const & name, bool managed)
+ : GenericNode(name, managed)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::CommandNode
+
+prefix_ senf::console::CommandNode::CommandNode(std::string const & name, bool managed)
+ : GenericNode(name, managed)
+{}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Node public header */
+
+#ifndef HH_Node_
+#define HH_Node_ 1
+
+// Custom includes
+#include <map>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/utility.hpp>
+#include "../Utils/intrusive_refcount.hh"
+#include "../Utils/Exception.hh"
+
+//#include "Node.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+
+ class DirectoryNode;
+ class CommandNode;
+
+ /** \brief
+ */
+ class GenericNode
+ : public intrusive_refcount_t<GenericNode>
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ typedef boost::intrusive_ptr<GenericNode> ptr;
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ std::string const & name() const;
+ DirectoryNode & parent() const;
+ bool managed() const;
+
+ protected:
+ explicit GenericNode(std::string const & name, bool managed = false);
+
+ void name(std::string const & name);
+ static void name(GenericNode & node, std::string const & name);
+ void parent(DirectoryNode * parent);
+
+ private:
+ bool release();
+
+ std::string name_;
+ bool managed_;
+ DirectoryNode * parent_;
+
+ friend class intrusive_refcount_base;
+ };
+
+ /** \brief
+ */
+ class DirectoryNode : public GenericNode
+ {
+ public:
+ typedef boost::intrusive_ptr<DirectoryNode> ptr;
+
+ void add(std::auto_ptr<GenericNode> node, bool uniquify = true);
+ void add(GenericNode & node, bool uniquify = true);
+
+ DirectoryNode & operator[](std::string const & name) const;
+ CommandNode & operator()(std::string const & name) const;
+
+ protected:
+ explicit DirectoryNode(std::string const & name, bool managed = false);
+
+ private:
+ void add(GenericNode::ptr node, bool uniquify);
+ GenericNode & lookup(std::string const & name) const;
+
+ typedef std::map<std::string, GenericNode::ptr> ChildMap;
+ ChildMap children_;
+ };
+
+ struct DuplicateNodeNameException : public senf::Exception
+ { DuplicateNodeNameException() : senf::Exception("Duplicate node name") {}};
+
+ struct UnknownNodeNameException : public senf::Exception
+ { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
+
+ /** \brief
+ */
+ class CommandNode : public GenericNode
+ {
+ public:
+ typedef boost::intrusive_ptr<CommandNode> ptr;
+
+ protected:
+ explicit CommandNode(std::string const & name, bool managed = false);
+
+ private:
+
+ };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Node.cci"
+//#include "Node.ct"
+//#include "Node.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Node.test unit tests */
+
+//#include "Node.test.hh"
+//#include "Node.test.ih"
+
+// Custom includes
+#include "Node.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(node)
+{}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Parse non-inline non-template implementation */
+
+#include "Parse.hh"
+#include "Parse.ih"
+
+// Custom includes
+#include <boost/iterator/transform_iterator.hpp>
+
+//#include "Parse.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+ struct ParserAccess
+ {
+ static void init(ParseCommandInfo & info)
+ { info.init(); }
+
+ static void setCommand(ParseCommandInfo & info, std::string const & commandPath)
+ { info.setCommand(commandPath); }
+
+ static void startArgument(ParseCommandInfo & info)
+ { info.startArgument(); }
+
+ static void endArgument(ParseCommandInfo & info)
+ { info.endArgument(); }
+
+ static void addToken(ParseCommandInfo & info, ArgumentToken const & token)
+ { info.addToken(token); }
+
+ static void finalize(ParseCommandInfo & info)
+ { info.finalize(); }
+
+ static ArgumentToken makeToken(std::string const & token)
+ { return ArgumentToken(token); }
+ };
+
+ struct ParseDispatcher
+ {
+ ParseDispatcher()
+ : info_ (0) {}
+
+ ParseCommandInfo * info_;
+
+ ParseCommandInfo & info() {
+ SENF_ASSERT( info_ );
+ return *info_;
+ }
+
+ struct BindInfo {
+ BindInfo( ParseDispatcher & d, ParseCommandInfo & i)
+ : dispatcher (d) { dispatcher.info_ = &i; }
+
+ ~BindInfo() { dispatcher.info_ = 0; }
+
+ ParseDispatcher & dispatcher;
+ };
+
+ void beginCommand(std::string const & command)
+ { ParserAccess::init(info());
+ ParserAccess::setCommand(info(), command); }
+
+ void endCommand()
+ { ParserAccess::finalize(info()); }
+
+ void pushArgument(std::string const & argument)
+ { ParserAccess::startArgument(info());
+ ParserAccess::addToken(info(), ParserAccess::makeToken(argument));
+ ParserAccess::endArgument(info()); }
+
+ void openGroup()
+ { ParserAccess::startArgument(info()); }
+
+ void closeGroup()
+ { ParserAccess::endArgument(info()); }
+
+ void pushPunctuation(std::string const & token)
+ { ParserAccess::addToken(info(), ParserAccess::makeToken(token)); }
+
+ void pushWord(std::string const & token)
+ { ParserAccess::addToken(info(), ParserAccess::makeToken(token)); }
+ };
+
+}}}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ParseCommandInfo
+
+struct senf::console::ParseCommandInfo::MakeRange
+{
+ MakeRange() {}
+ MakeRange(ParseCommandInfo::token_iterator b) : b_ (b) {}
+
+ senf::console::ParseCommandInfo::token_iterator b_;
+
+ typedef ParseCommandInfo::argument_value_type result_type;
+
+ result_type operator()(TempArguments::iterator::value_type const & v) const {
+ return result_type( b_ + v.first, b_ + v.second );
+ }
+};
+
+prefix_ void senf::console::ParseCommandInfo::finalize()
+{
+ arguments_.resize( tempArguments_.size() );
+
+ std::copy( boost::make_transform_iterator( tempArguments_.begin(),
+ MakeRange(tokens_.begin()) ),
+ boost::make_transform_iterator( tempArguments_.end(),
+ MakeRange() ),
+ arguments_.begin() );
+
+ tempArguments_.clear();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SingleCommandParser
+
+struct senf::console::SingleCommandParser::Impl
+{
+ detail::ParseDispatcher dispatcher;
+ detail::CommandGrammar<detail::ParseDispatcher>::Context context;
+ detail::CommandGrammar<detail::ParseDispatcher> grammar;
+ detail::SkipGrammar skipGrammar;
+
+ Impl() : dispatcher(), context(), grammar(dispatcher, context) {}
+};
+
+prefix_ senf::console::SingleCommandParser::SingleCommandParser()
+ : impl_ (new Impl())
+{}
+
+prefix_ senf::console::SingleCommandParser::~SingleCommandParser()
+{}
+
+prefix_ bool senf::console::SingleCommandParser::parseCommand(std::string command,
+ ParseCommandInfo & info)
+{
+ detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
+ return boost::spirit::parse( command.c_str(), impl().grammar, impl().skipGrammar ).full;
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Parse.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Parse inline non-template implementation */
+
+// We do NOT want to include the complete parser definition into every other compilation unit
+// (disabled) #include "Parse.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ArgumentToken
+
+prefix_ std::string const & senf::console::ArgumentToken::value()
+ const
+{
+ return token_;
+}
+
+prefix_ senf::console::ArgumentToken::ArgumentToken(std::string token)
+ : token_ (token)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ParseCommandInfo
+
+prefix_ std::string const & senf::console::ParseCommandInfo::commandPath()
+ const
+{
+ return commandPath_;
+}
+
+prefix_ senf::console::ParseCommandInfo::size_type senf::console::ParseCommandInfo::arguments()
+ const
+{
+ return arguments_.size();
+}
+
+prefix_ senf::console::ParseCommandInfo::argument_iterator
+senf::console::ParseCommandInfo::begin_arguments()
+ const
+{
+ return arguments_.begin();
+}
+
+prefix_ senf::console::ParseCommandInfo::argument_iterator
+senf::console::ParseCommandInfo::end_arguments()
+ const
+{
+ return arguments_.end();
+}
+
+prefix_ senf::console::ParseCommandInfo::size_type senf::console::ParseCommandInfo::tokens()
+ const
+{
+ return tokens_.size();
+}
+
+prefix_ senf::console::ParseCommandInfo::token_iterator
+senf::console::ParseCommandInfo::begin_tokens()
+ const
+{
+ return tokens_.begin();
+}
+
+prefix_ senf::console::ParseCommandInfo::token_iterator
+senf::console::ParseCommandInfo::end_tokens()
+ const
+{
+ return tokens_.end();
+}
+
+////////////////////////////////////////
+// private members
+
+prefix_ void senf::console::ParseCommandInfo::init()
+{
+ commandPath_ = "";
+ tokens_.clear();
+ arguments_.clear();
+ tempArguments_.clear();
+}
+
+prefix_ void senf::console::ParseCommandInfo::setCommand(std::string const & commandPath)
+{
+ commandPath_ = commandPath;
+}
+
+prefix_ void senf::console::ParseCommandInfo::startArgument()
+{
+ tempArguments_.push_back( TempArgumentRange( tokens_.size(), tokens_.size() ) );
+}
+
+prefix_ void senf::console::ParseCommandInfo::endArgument()
+{
+ tempArguments_.back().second = tokens_.size();
+}
+
+prefix_ void senf::console::ParseCommandInfo::addToken(ArgumentToken const & token)
+{
+ tokens_.push_back(token);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SingleCommandParser
+
+prefix_ senf::console::SingleCommandParser::Impl & senf::console::SingleCommandParser::impl()
+{
+ SENF_ASSERT(impl_);
+ return *impl_;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Parse public header */
+
+#ifndef HH_Parse_
+#define HH_Parse_ 1
+
+// Custom includes
+#include <string>
+#include <vector>
+#include <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/range/iterator_range.hpp>
+
+//#include "Parse.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+
+ namespace detail { struct ParserAccess; }
+
+ /** \brief
+ */
+ class ArgumentToken
+ {
+ public:
+ std::string const & value() const;
+
+ protected:
+
+ private:
+ explicit ArgumentToken(std::string token);
+
+ std::string token_;
+
+ friend class detail::ParserAccess;
+ };
+
+
+ /** \brief
+ */
+ class ParseCommandInfo
+ {
+ typedef std::vector<ArgumentToken> Tokens;
+
+ public:
+ typedef Tokens::const_iterator token_iterator;
+ typedef boost::iterator_range<token_iterator> argument_value_type;
+
+ private:
+ typedef std::vector<argument_value_type> Arguments;
+
+ public:
+ typedef Arguments::const_iterator argument_iterator;
+ typedef Arguments::size_type size_type;
+
+ std::string const & commandPath() const;
+
+ size_type arguments() const;
+ argument_iterator begin_arguments() const;
+ argument_iterator end_arguments() const;
+
+ size_type tokens() const;
+ token_iterator begin_tokens() const;
+ token_iterator end_tokens() const;
+
+ protected:
+
+ private:
+ void init();
+ void setCommand(std::string const & commandPath);
+ void startArgument();
+ void endArgument();
+ void addToken(ArgumentToken const & token);
+ void finalize();
+
+ struct MakeRange;
+
+ std::string commandPath_;
+
+ typedef std::pair<Tokens::size_type, Tokens::size_type> TempArgumentRange;
+ typedef std::vector<TempArgumentRange> TempArguments;
+
+ Tokens tokens_;
+ Arguments arguments_;
+ TempArguments tempArguments_;
+
+ friend class detail::ParserAccess;
+ };
+
+ /** \brief
+ */
+ class SingleCommandParser
+ : boost::noncopyable
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ SingleCommandParser();
+ ~SingleCommandParser();
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool parseCommand(std::string command, ParseCommandInfo & info);
+
+ private:
+ struct Impl;
+
+ Impl & impl();
+
+ boost::scoped_ptr<Impl> impl_;
+ };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Parse.cci"
+//#include "Parse.ct"
+//#include "Parse.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Parse internal header */
+
+#ifndef IH_Parse_
+#define IH_Parse_ 1
+
+// Custom includes
+#include <boost/regex.hpp>
+#include <boost/spirit.hpp>
+#include <boost/spirit/utility/regex.hpp>
+#include <boost/spirit/actor.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+ struct append_action
+ {
+ template <class T, class Value>
+ void act(T & ref, Value const & value) const
+ { ref += T(1, value); }
+
+ template <class T, class Iterator>
+ void act(T & ref, Iterator const & f, Iterator const & l) const
+ { ref += T(f,l); }
+ };
+
+ template <class T>
+ inline boost::spirit::ref_value_actor<T, append_action>
+ append_a(T & ref)
+ {
+ return boost::spirit::ref_value_actor<T, append_action>(ref);
+ }
+
+ template <class T, class Value>
+ inline boost::spirit::ref_const_ref_actor<T, Value, append_action>
+ append_a(T & ref, Value const & value)
+ {
+ return boost::spirit::ref_const_ref_actor<T, Value, append_action>(ref, value);
+ }
+
+ template <class ParseDispatcher>
+ struct CommandGrammar : boost::spirit::grammar<CommandGrammar<ParseDispatcher> >
+ {
+ ///////////////////////////////////////////////////////////////////////////
+ // The parse context (variables needed while parsing)
+
+ struct Context {
+ std::string str;
+ char ch;
+ };
+
+ Context & context;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Dispatching semantic actions
+
+ ParseDispatcher & dispatcher;
+
+ struct Dispatch_actor
+ {
+ Dispatch_actor(boost::function<void ()> fn_) : fn (fn_) {}
+
+ template <class Value>
+ void operator()(Value const & value) const
+ { fn(); }
+
+ template <class Iterator>
+ void operator()(Iterator const & f, Iterator const & l) const
+ { fn(); }
+
+ boost::function<void ()> fn;
+ };
+
+ template <class Callback>
+ Dispatch_actor dispatch(Callback cb) const
+ { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher))); }
+
+ template <class Callback, class Arg>
+ Dispatch_actor dispatch(Callback cb, Arg const & arg) const
+ { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg)); }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ CommandGrammar(ParseDispatcher & d, Context & c)
+ : context(c), dispatcher(d) {}
+
+ template <class Scanner>
+ struct definition
+ {
+ boost::spirit::rule<Scanner> command, path, argument, word, string, hexstring, token;
+ boost::spirit::rule<Scanner> punctuation, hexbyte, balanced_tokens, simple_argument;
+ boost::spirit::rule<Scanner> complex_argument;
+
+ definition(CommandGrammar const & self) {
+ using namespace boost::spirit;
+ typedef ParseDispatcher PD;
+
+ command
+ = path [ self.dispatch(&PD::beginCommand,
+ boost::cref(self.context.str)) ]
+ >> * argument
+ >> ! ch_p(';')
+ >> eps_p [ self.dispatch(&PD::endCommand) ]
+ ;
+
+ argument
+ = simple_argument [ self.dispatch(&PD::pushArgument,
+ boost::cref(self.context.str)) ]
+ | complex_argument
+ ;
+
+ simple_argument // All these return their value in context.str
+ = string
+ | hexstring
+ | path
+ ;
+
+ complex_argument // Argument consists of multiple tokens
+ = ch_p('(') [ self.dispatch(&PD::openGroup) ]
+ >> * token
+ >> ch_p(')') [ self.dispatch(&PD::closeGroup) ]
+ ;
+
+ string // Returns value in context.str
+ = eps_p [ clear_a(self.context.str) ]
+ >> lexeme_d
+ [
+ ch_p('"')
+ >> * ( ( lex_escape_ch_p[ assign_a(self.context.ch) ]
+ - '"'
+ ) [ append_a(self.context.str,
+ self.context.ch) ]
+ )
+ >> ch_p('"')
+ ]
+ ;
+
+ hexstring // Returns value in context.str
+ = eps_p [ clear_a(self.context.str) ]
+ >> confix_p( "x\"", * hexbyte, '"' )
+ ;
+
+ path // Returns value in context.str
+ = eps_p [ clear_a(self.context.str) ]
+ >> ( ! ch_p('/') [ append_a(self.context.str) ]
+ )
+ >> ( word [ append_a(self.context.str) ]
+ % ch_p('/') [ append_a(self.context.str) ]
+ )
+ ;
+
+ balanced_tokens
+ = ch_p('(') [ self.dispatch(&PD::pushPunctuation, "(") ]
+ >> * token
+ >> ch_p(')') [ self.dispatch(&PD::pushPunctuation, ")") ]
+ ;
+
+ token
+ = simple_argument [ self.dispatch(&PD::pushWord,
+ boost::cref(self.context.str)) ]
+ | punctuation [ self.dispatch(&PD::pushPunctuation,
+ boost::cref(self.context.str)) ]
+ | balanced_tokens
+ ;
+
+ punctuation // Returns value in context.str
+ = regex_p("[,=]") [ assign_a(self.context.str) ]
+ ;
+
+ word
+ = regex_p("[^ \t\n\r;,=(){}/\"]+")
+ ;
+
+ hexbyte
+ = uint_parser<char, 16, 2, 2>()
+ [ append_a(self.context.str) ]
+ ;
+
+ BOOST_SPIRIT_DEBUG_RULE(command);
+ BOOST_SPIRIT_DEBUG_RULE(path);
+ BOOST_SPIRIT_DEBUG_RULE(argument);
+ BOOST_SPIRIT_DEBUG_RULE(word);
+ BOOST_SPIRIT_DEBUG_RULE(string);
+ BOOST_SPIRIT_DEBUG_RULE(hexstring);
+ BOOST_SPIRIT_DEBUG_RULE(token);
+ BOOST_SPIRIT_DEBUG_RULE(punctuation);
+ BOOST_SPIRIT_DEBUG_RULE(hexbyte);
+ BOOST_SPIRIT_DEBUG_RULE(balanced_tokens);
+ BOOST_SPIRIT_DEBUG_RULE(simple_argument);
+ BOOST_SPIRIT_DEBUG_RULE(complex_argument);
+ }
+
+ boost::spirit::rule<Scanner> const & start() const { return command; }
+ };
+ };
+
+ struct SkipGrammar
+ : public boost::spirit::grammar<SkipGrammar>
+ {
+ template <class Scanner>
+ struct definition
+ {
+ boost::spirit::rule<Scanner> rule;
+
+ definition(SkipGrammar const & self) {
+ rule
+ = boost::spirit::regex_p("[ \t]+")
+ | boost::spirit::comment_p('#')
+ ;
+ }
+
+ boost::spirit::rule<Scanner> const & start() const { return rule; }
+ };
+ };
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Parse.test unit tests */
+
+//#include "Parse.test.hh"
+//#include "Parse.test.ih"
+
+// Custom includes
+#include <sstream>
+#include "Parse.hh"
+#include "Parse.ih"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace
+{
+ struct TestParseDispatcher
+ {
+ TestParseDispatcher(std::ostream & os) : os_ (os) {}
+
+ std::ostream & os_;
+
+ void beginCommand(std::string const & command)
+ { os_ << "beginCommand( " << command << " )\n"; }
+ void endCommand()
+ { os_ << "endCommand()\n"; }
+
+ void pushArgument(std::string const & argument)
+ { os_ << "pushArgument( " << argument << " )\n"; }
+ void openGroup()
+ { os_ << "openGroup()\n"; }
+ void closeGroup()
+ { os_ << "closeGroup()\n"; }
+ void pushPunctuation(std::string const & token)
+ { os_ << "pushPunctuation( " << token << " )\n"; }
+ void pushWord(std::string const & token)
+ { os_ << "pushWord( " << token << " )\n"; }
+ };
+}
+
+BOOST_AUTO_UNIT_TEST(commandParser)
+{
+ senf::console::detail::CommandGrammar<TestParseDispatcher>::Context context;
+ std::stringstream ss;
+ TestParseDispatcher dispatcher (ss);
+ senf::console::detail::CommandGrammar<TestParseDispatcher> grammar (dispatcher, context);
+ senf::console::detail::SkipGrammar skipGrammar;
+
+ char text[] =
+ "# Comment\n"
+ "doo / bii / doo arg/../path"
+ " flab::blub"
+ " 123.434>a"
+ " (a,b,c (huhu))"
+ " \"foo\\\"bar\" #\n"
+ " x\"01 02 # Inner comment\n"
+ " 0304\"";
+
+ BOOST_CHECK( boost::spirit::parse(
+ text,
+ grammar,
+ skipGrammar ) . full );
+ BOOST_CHECK_EQUAL( ss.str(),
+ "beginCommand( doo/bii/doo )\n"
+ "pushArgument( arg/../path )\n"
+ "pushArgument( flab::blub )\n"
+ "pushArgument( 123.434>a )\n"
+ "openGroup()\n"
+ "pushWord( a )\n"
+ "pushPunctuation( , )\n"
+ "pushWord( b )\n"
+ "pushPunctuation( , )\n"
+ "pushWord( c )\n"
+ "pushPunctuation( ( )\n"
+ "pushWord( huhu )\n"
+ "pushPunctuation( ) )\n"
+ "closeGroup()\n"
+ "pushArgument( foo\"bar )\n"
+ "pushArgument( \x01\x02\x03\x04 )\n"
+ "endCommand()\n" );
+}
+
+BOOST_AUTO_UNIT_TEST(singleCommandParser)
+{
+ senf::console::SingleCommandParser parser;
+
+ char const text[] =
+ "# Comment\n"
+ "doo / bii / doo arg/../path"
+ " flab::blub"
+ " 123.434>a"
+ " (a,b,c (huhu))"
+ " \"foo\\\"bar\" #\n"
+ " x\"01 02 # Inner comment\n"
+ " 0304\"";
+
+ senf::console::ParseCommandInfo info;
+ BOOST_CHECK( parser.parseCommand(text, info) );
+
+ BOOST_CHECK_EQUAL( info.commandPath(), "doo/bii/doo" );
+ BOOST_REQUIRE_EQUAL( info.arguments(), 6u );
+ BOOST_REQUIRE_EQUAL( info.tokens(), 13u );
+
+ char const * tokens[] = { "arg/../path",
+ "flab::blub",
+ "123.434>a",
+ "a", ",", "b", ",", "c", "(", "huhu", ")",
+ "foo\"bar",
+ "\x01\x02\x03\x04" };
+
+ BOOST_REQUIRE_EQUAL( info.begin_arguments()[0].size(), 1u );
+ BOOST_CHECK_EQUAL( info.begin_arguments()[0].begin()->value(), tokens[0] );
+
+ BOOST_REQUIRE_EQUAL( info.begin_arguments()[1].size(), 1u );
+ BOOST_CHECK_EQUAL( info.begin_arguments()[1].begin()->value(), tokens[1] );
+
+ BOOST_REQUIRE_EQUAL( info.begin_arguments()[2].size(), 1u );
+ BOOST_CHECK_EQUAL( info.begin_arguments()[2].begin()->value(), tokens[2] );
+
+ BOOST_REQUIRE_EQUAL( info.begin_arguments()[3].size(), 8u );
+ for (unsigned i (0); i<8; ++i)
+ BOOST_CHECK_EQUAL( info.begin_arguments()[3].begin()[i].value(), tokens[3+i] );
+
+ BOOST_REQUIRE_EQUAL( info.begin_arguments()[4].size(), 1u );
+ BOOST_CHECK_EQUAL( info.begin_arguments()[4].begin()->value(), tokens[11] );
+
+ BOOST_REQUIRE_EQUAL( info.begin_arguments()[5].size(), 1u );
+ BOOST_CHECK_EQUAL( info.begin_arguments()[5].begin()->value(), tokens[12] );
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+# -*- python -*-
+
+Import('env')
+import SENFSCons
+
+###########################################################################
+
+sources = SENFSCons.GlobSources()
+SENFSCons.StandardTargets(env)
+SENFSCons.Lib(env,
+ library = 'Console',
+ sources = sources,
+ LIBS = [ 'Socket', 'Scheduler', 'Utils' ])
+SENFSCons.Doxygen(env)
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// Definition of non-inline non-template functions
+
+//#include "test.hh"
+//#include "test.ih"
+
+// Custom includes
+#define BOOST_AUTO_TEST_MAIN
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
+// End: