\brief Config non-inline non-template implementation */
#include "Config.hh"
-//#include "Config.ih"
+#include "Config.ih"
// Custom includes
+#include "../Utils/membind.hh"
//#include "Config.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::console::ConfigFile
+// senf::console::detail::RestrictedExecutor
-#ifndef DOXYGEN
-
-namespace {
- struct BindPolicy
- {
- BindPolicy(senf::console::Executor & e, senf::console::Executor::SecurityPolicy p)
- : e_ (e)
- { e_.policy(p); }
-
- ~BindPolicy()
- { e_.policy(senf::console::Executor::SecurityPolicy()); }
-
- senf::console::Executor & e_;
- };
+prefix_ senf::console::detail::RestrictedExecutor::RestrictedExecutor(DirectoryNode & root)
+{
+ executor_
+ .chroot(root)
+ .policy(senf::membind(&RestrictedExecutor::policyCallback, this));
}
-#endif
+prefix_ void
+senf::console::detail::RestrictedExecutor::execute(std::ostream & output,
+ ParseCommandInfo const & command)
+{
+ executor_.execute(output, command);
+}
-prefix_ void senf::console::ConfigFile::parse(DirectoryNode & restrict)
+prefix_ void
+senf::console::detail::RestrictedExecutor::operator()(std::ostream & output,
+ ParseCommandInfo const & command)
{
- DirectoryNode::ptr r (restrict.thisptr());
- BindPolicy bp ( executor_,
- boost::bind(&ConfigFile::policyCallback, this, r, _1, _2) );
- if (! parser_.parseFile(filename_, boost::bind<void>( boost::ref(executor_),
- boost::ref(std::cerr),
- _1 )) )
- throw SyntaxErrorException();
- insertParsedNode(r);
+ execute(output, command);
}
-prefix_ bool senf::console::ConfigFile::parsed(GenericNode & node)
+prefix_ bool senf::console::detail::RestrictedExecutor::parsed(GenericNode & node)
const
{
ParsedNodes::const_iterator i (parsedNodes_.begin());
return false;
}
-prefix_ void senf::console::ConfigFile::policyCallback(DirectoryNode::ptr restrict,
- DirectoryNode & dir,
- std::string const & name)
+prefix_ void senf::console::detail::RestrictedExecutor::policyCallback(DirectoryNode & dir,
+ std::string const & name)
{
if (dir.hasChild(name)) {
GenericNode & item (dir.get(name));
- if (restrict && ! item.isChildOf(*restrict) && ! item.isDirectory())
+ if (restrict_ && ! item.isChildOf(*restrict_) && ! item.isDirectory())
throw Executor::IgnoreCommandException();
if (parsed(item))
throw Executor::IgnoreCommandException();
}
- else if (restrict && ! dir.isChildOf(*restrict))
+ else if (restrict_ && ! dir.isChildOf(*restrict_))
throw Executor::IgnoreCommandException();
}
};
}
-prefix_ void senf::console::ConfigFile::insertParsedNode(DirectoryNode::ptr node)
+prefix_ void
+senf::console::detail::RestrictedExecutor::insertParsedNode(DirectoryNode & node)
{
parsedNodes_.erase(
- std::remove_if(parsedNodes_.begin(), parsedNodes_.end(), RemoveNodesFn(node)),
+ std::remove_if(parsedNodes_.begin(), parsedNodes_.end(), RemoveNodesFn(node.thisptr())),
parsedNodes_.end());
- parsedNodes_.push_back(node);
+ parsedNodes_.push_back(node.thisptr());
}
///////////////////////////////////////////////////////////////////////////
+// senf::console::ConfigBundle
+
+prefix_ void senf::console::ConfigBundle::parse()
+{
+ detail::RestrictedExecutor::RestrictGuard guard (executor_);
+ parseInternal();
+}
+
+prefix_ void senf::console::ConfigBundle::parse(DirectoryNode & restrict)
+{
+ detail::RestrictedExecutor::RestrictGuard guard (executor_, restrict);
+ parseInternal();
+}
+
+prefix_ void senf::console::ConfigBundle::parseInternal()
+{
+ Sources::const_iterator i (sources_.begin());
+ Sources::const_iterator const i_end (sources_.end());
+ for (; i != i_end; ++i)
+ (*i)->parse(executor_);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::RestrictedExecutor::RestrictGuard
+
+prefix_ senf::console::detail::RestrictedExecutor::RestrictGuard::
+RestrictGuard(RestrictedExecutor & executor)
+ : executor_ (executor)
+{
+ // This MUST BE root() not chroot() since restriction does NOT follow symlinks.
+ // Therefore, if chroot() is a directory of symlinks, restricting to it will
+ // execute NOTHING.
+ executor_.restrict_ = senf::console::root().thisptr();
+}
+
+prefix_ senf::console::detail::RestrictedExecutor::RestrictGuard::
+RestrictGuard(RestrictedExecutor & executor, DirectoryNode & restrict)
+ : executor_ (executor)
+{
+ executor_.restrict_ = restrict.thisptr();
+}
-prefix_ void senf::console::readConfig(std::string const & filename, DirectoryNode & root)
+prefix_ senf::console::detail::RestrictedExecutor::RestrictGuard::~RestrictGuard()
{
- ConfigFile cfg (filename, root);
- cfg.parse();
+ if (! std::uncaught_exception())
+ executor_.insertParsedNode( *executor_.restrict_ );
+ executor_.restrict_ = senf::console::root().thisptr();
}
///////////////////////////////cc.e////////////////////////////////////////
/** \file
\brief Config inline non-template implementation */
-//#include "Config.ih"
+#include "Config.ih"
// Custom includes
#include "../Utils/membind.hh"
///////////////////////////////cci.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::console::ConfigFile
+// senf::console::ConfigBundle
-prefix_ senf::console::ConfigFile::ConfigFile(std::string const & filename,
- DirectoryNode & root)
- : filename_ (filename)
+prefix_ senf::console::ConfigBundle::ConfigBundle()
+{}
+
+prefix_ senf::console::ConfigBundle::ConfigBundle(DirectoryNode & root)
+ : executor_ (root)
+{}
+
+prefix_ void senf::console::ConfigBundle::add(detail::ConfigSource::ptr source)
+{
+ sources_.push_back(source);
+}
+
+prefix_ bool senf::console::ConfigBundle::complete()
+ const
{
- executor_.chroot(root);
+ return executor_.complete();
}
-prefix_ void senf::console::ConfigFile::parse()
+prefix_ bool senf::console::ConfigBundle::parsed(GenericNode & node)
+ const
+{
+ return executor_.parsed(node);
+}
+
+prefix_ void senf::console::ConfigBundle::reset()
{
- parse(executor_.chroot());
+ executor_.reset();
}
-prefix_ bool senf::console::ConfigFile::complete()
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::RestrictedExecutor
+
+prefix_ bool senf::console::detail::RestrictedExecutor::complete()
const
{
return parsedNodes_.size() == 1
&& *parsedNodes_[0].lock() == executor_.chroot();
}
-prefix_ void senf::console::ConfigFile::reset()
+prefix_ void senf::console::detail::RestrictedExecutor::reset()
{
parsedNodes_.clear();
}
+prefix_ senf::console::DirectoryNode & senf::console::detail::RestrictedExecutor::root()
+ const
+{
+ return executor_.chroot();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ConfigSource
+
+prefix_ void senf::console::detail::ConfigSource::parse(RestrictedExecutor & executor)
+{
+ v_parse(executor);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::BundleMixin
+
+prefix_ senf::console::detail::BundleMixin::BundleMixin()
+{}
+
+prefix_ senf::console::detail::BundleMixin::BundleMixin(DirectoryNode & root)
+ : bundle_ (root)
+{}
+
+prefix_ void senf::console::detail::BundleMixin::parse()
+{
+ bundle_.parse();
+}
+
+prefix_ void senf::console::detail::BundleMixin::parse(DirectoryNode & restrict)
+{
+ bundle_.parse(restrict);
+}
+
+prefix_ bool senf::console::detail::BundleMixin::complete()
+ const
+{
+ return bundle_.complete();
+}
+
+prefix_ bool senf::console::detail::BundleMixin::parsed(GenericNode & node)
+ const
+{
+ return bundle_.parsed(node);
+}
+
+prefix_ void senf::console::detail::BundleMixin::reset()
+{
+ bundle_.reset();
+}
+
+prefix_ void senf::console::detail::BundleMixin::add(ConfigSource::ptr source)
+{
+ bundle_.add(source);
+}
+
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
#include "Executor.hh"
//#include "Config.mpp"
+#include "Config.ih"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
namespace console {
- /** \brief Console node tree based config file parser
-
- A ConfigFile instance allows flexible parsing of a config file against the console node
- tree. If you just want to parse a file completely, the senf::console::readConfig() function
- will do that. ConfigFile however allows to incrementally parse only a subdirectory of the
- complete configuration file.
- \code
- senf::console::ConfigFile cf ("/my/config/file")
-
- // Parse only statements under the directory of some object. The object 'ob'
- // must have been registered somewhere in the node tree
- cf.parse(ob.dir);
-
- // Parse rest of the config file
- cf.parse();
- \endcode
+ /** \brief
*/
- class ConfigFile
- : boost::noncopyable
+ class ConfigBundle
{
public:
///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ ///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
- explicit ConfigFile(std::string const & filename, DirectoryNode & root = root());
- ///< Create ConfigFile object for \a filename
- /**< The \a filename configuration file will be parsed using
- parse() calls. All configuration statements will be
- interpreted relative to \a root as root node. */
+ ConfigBundle();
+ ConfigBundle(DirectoryNode & root);
+
+ // default default constructor
+ // default copy constructor
+ // default copy assignment
+ // default destructor
+
+ // no conversion constructors
///@}
///////////////////////////////////////////////////////////////////////////
+ void add(detail::ConfigSource::ptr source);
+
void parse(); ///< Parse config file
/**< All nodes already parsed are skipped */
void parse(DirectoryNode & restrict); ///< Parse config file under \a restrict
bool complete() const; ///< \c true, if all nodes have been parsed
bool parsed(GenericNode & node) const; ///< \c true. if \a node has been parsed
-
void reset(); ///< Reset node parse info state
/**< After a call to reset(), all information about already
parsed nodes is cleared. Calling parse() will parse the
protected:
private:
- void policyCallback(DirectoryNode::ptr restrict, DirectoryNode & dir,
- std::string const & item);
+ void parseInternal();
- void insertParsedNode(DirectoryNode::ptr node);
+ typedef std::vector<detail::ConfigSource::ptr> Sources;
- typedef std::vector<DirectoryNode::weak_ptr> ParsedNodes;
+ Sources sources_;
+ detail::RestrictedExecutor executor_;
+ };
- std::string filename_;
- CommandParser parser_;
- Executor executor_;
+namespace detail {
+ // hrmpf ... Can't place this into Config.ih ...
- ParsedNodes parsedNodes_;
- };
+ class BundleMixin
+ {
+ public:
+ BundleMixin();
+ BundleMixin(DirectoryNode & root);
- /** \brief Read configuration file
+ void parse(); ///< Parse config file
+ /**< All nodes already parsed are skipped */
+ void parse(DirectoryNode & restrict); ///< Parse config file under \a restrict
+ /**< Only nodes which are children of \a restrict are
+ parsed. */
- The configuration file \a filename will be loaded, interpreting all node's relative to \a
- root as root node.
+ bool complete() const; ///< \c true, if all nodes have been parsed
+ bool parsed(GenericNode & node) const; ///< \c true. if \a node has been parsed
+ void reset(); ///< Reset node parse info state
+ /**< After a call to reset(), all information about already
+ parsed nodes is cleared. Calling parse() will parse the
+ complete config file again. */
- This function uses a local ConfigFile object to perform the parsing.
+ protected:
+ void add(ConfigSource::ptr source);
- \related ConfigFile
- */
- void readConfig(std::string const & filename, DirectoryNode & root = root());
+ private:
+ ConfigBundle bundle_;
+ };
-}}
+}}}
///////////////////////////////hh.e////////////////////////////////////////
#include "Config.cci"
--- /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 Config internal header */
+
+#ifndef IH_Console_Config_
+#define IH_Console_Config_ 1
+
+// Custom includes
+#include <boost/utility.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include "Executor.hh"
+#include "../Utils/intrusive_refcount.hh"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+ class RestrictedExecutor
+ : boost::noncopyable
+ {
+ public:
+ typedef void result_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ //\/name Structors and default members
+ ///\{
+
+ RestrictedExecutor(DirectoryNode & root = senf::console::root());
+
+ ///\}
+ ///////////////////////////////////////////////////////////////////////////
+
+ 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.
+ Same as execute(). */
+
+ bool complete() const; ///< \c true, if all nodes have been parsed
+ bool parsed(GenericNode & node) const; ///< \c true. if \a node has been parsed
+ void reset(); ///< Reset node parse info state
+ /**< After a call to reset(), all information about already
+ parsed nodes is cleared. Calling parse() will parse the
+ complete config file again. */
+
+ DirectoryNode & root() const;
+
+ class RestrictGuard;
+
+ protected:
+
+ private:
+ void policyCallback(DirectoryNode & dir, std::string const & item);
+ void insertParsedNode(DirectoryNode & node);
+
+ typedef std::vector<DirectoryNode::weak_ptr> ParsedNodes;
+
+ Executor executor_;
+ ParsedNodes parsedNodes_;
+ DirectoryNode::ptr restrict_;
+
+ friend class RestrictGuard;
+ };
+
+ class RestrictedExecutor::RestrictGuard
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ //\/name Structors and default members
+ ///\{
+
+ explicit RestrictGuard(RestrictedExecutor & executor);
+ RestrictGuard(RestrictedExecutor & executor, DirectoryNode & restrict);
+ ~RestrictGuard();
+
+ ///\}
+ ///////////////////////////////////////////////////////////////////////////
+
+ protected:
+
+ private:
+ RestrictedExecutor & executor_;
+
+ };
+
+ /** \brief
+ */
+ class ConfigSource
+ : public senf::intrusive_refcount
+ {
+ public:
+ typedef boost::intrusive_ptr<ConfigSource> ptr;
+
+ void parse(RestrictedExecutor & executor);
+
+ protected:
+
+ private:
+ virtual void v_parse(RestrictedExecutor & executor) = 0;
+ };
+
+}}}
+
+///////////////////////////////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 ConfigFile non-inline non-template implementation */
+
+#include "ConfigFile.hh"
+#include "ConfigFile.ih"
+
+// Custom includes
+
+//#include "ConfigFile.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ConfigFileSource
+
+prefix_ void senf::console::detail::ConfigFileSource::v_parse(RestrictedExecutor & executor)
+{
+ if (! parser_.parseFile(filename_, boost::bind( boost::ref(executor),
+ boost::ref(std::cerr),
+ _1 )) )
+ throw SyntaxErrorException();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ void senf::console::readConfig(std::string const & filename, DirectoryNode & root)
+{
+ ConfigFile cfg (filename, root);
+ cfg.parse();
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "ConfigFile.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 ConfigFile inline non-template implementation */
+
+#include "ConfigFile.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ConfigFileSource
+
+prefix_ senf::console::detail::ConfigFileSource::ptr
+senf::console::detail::ConfigFileSource::create(std::string const & filename)
+{
+ return ptr(new ConfigFileSource(filename));
+}
+
+prefix_ senf::console::detail::ConfigFileSource::ConfigFileSource(std::string const & filename)
+ : filename_ (filename)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ConfigFile
+
+prefix_ senf::console::ConfigFile::ConfigFile(std::string const & filename,
+ DirectoryNode & root)
+ : detail::BundleMixin(root)
+{
+ add(detail::ConfigFileSource::create(filename));
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ senf::console::detail::ConfigFileSource::ptr
+senf::console::FileConfig(std::string const & filename)
+{
+ return detail::ConfigFileSource::create(filename);
+}
+
+///////////////////////////////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 ConfigFile public header */
+
+#ifndef HH_ConfigFile_
+#define HH_ConfigFile_ 1
+
+// Custom includes
+#include "Config.hh"
+
+//#include "ConfigFile.mpp"
+#include "ConfigFile.ih"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+
+ /** \brief Console node tree based config file parser
+
+ A ConfigFile instance allows flexible parsing of a config file against the console node
+ tree. If you just want to parse a file completely, the senf::console::readConfig() function
+ will do that. ConfigFile however allows to incrementally parse only a subdirectory of the
+ complete configuration file.
+ \code
+ senf::console::ConfigFile cf ("/my/config/file")
+
+ // Parse only statements under the directory of some object. The object 'ob'
+ // must have been registered somewhere in the node tree
+ cf.parse(ob.dir);
+
+ // Parse rest of the config file
+ cf.parse();
+ \endcode
+ */
+ class ConfigFile
+ : public detail::BundleMixin
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ explicit ConfigFile(std::string const & filename, DirectoryNode & root = root());
+ ///< Create ConfigFile object for \a filename
+ /**< The \a filename configuration file will be parsed using
+ parse() calls. All configuration statements will be
+ interpreted relative to \a root as root node. */
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+ };
+
+ /** \brief Read configuration file
+
+ The configuration file \a filename will be loaded, interpreting all node's relative to \a
+ root as root node.
+
+ This function uses a local ConfigFile object to perform the parsing.
+
+ \related ConfigFile
+ */
+ void readConfig(std::string const & filename, DirectoryNode & root = root());
+
+ detail::ConfigFileSource::ptr FileConfig(std::string const & filename);
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "ConfigFile.cci"
+//#include "ConfigFile.ct"
+//#include "ConfigFile.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 ConfigFile internal header */
+
+#ifndef IH_ConfigFile_
+#define IH_ConfigFile_ 1
+
+// Custom includes
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+ class ConfigFileSource : public ConfigSource
+ {
+ public:
+ static ptr create(std::string const & filename);
+
+ private:
+ ConfigFileSource(std::string const & filename);
+
+ virtual void v_parse(RestrictedExecutor & executor);
+
+ std::string filename_;
+ CommandParser parser_;
+ };
+
+}}}
+
+///////////////////////////////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:
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief Config.test unit tests */
+ \brief ConfigFile.test unit tests */
-//#include "Config.test.hh"
-//#include "Config.test.ih"
+//#include "ConfigFile.test.hh"
+//#include "ConfigFile.test.ih"
// Custom includes
-#include "Config.hh"
+#include "ConfigFile.hh"
#include <fstream>
#include "ScopedDirectory.hh"
#include "ParsedCommand.hh"
std::string name_;
std::ofstream file_;
};
-
}
/// Thrown by the SecurityPolicy to silently ignore a command
struct IgnoreCommandException {};
+ typedef void result_type;
+
///////////////////////////////////////////////////////////////////////////
//\/name Structors and default members
///\{
#ifndef DOXYGEN
- struct ParserAccess
- {
- static void init(ParseCommandInfo & info)
- { info.init(); }
-
- static void setBuiltin(ParseCommandInfo & info, ParseCommandInfo::BuiltinCommand builtin)
- { info.setBuiltin(builtin); }
-
- static void setCommand(ParseCommandInfo & info, std::vector<Token> & commandPath)
- { info.setCommand(commandPath); }
-
- static void addToken(ParseCommandInfo & info, Token const & token)
- { info.addToken(token); }
- };
-
struct ParseDispatcher
{
- ParseCommandInfo info_;
+ ParseCommandInfo * info_;
CommandParser::Callback cb_;
struct BindInfo {
- BindInfo( ParseDispatcher & d, CommandParser::Callback cb)
- : dispatcher (d) { dispatcher.cb_ = cb; }
- ~BindInfo() { dispatcher.cb_ = 0; }
+ BindInfo( ParseDispatcher & d, ParseCommandInfo & info, CommandParser::Callback cb)
+ : dispatcher (d) { dispatcher.info_ = &info; dispatcher.cb_ = cb; }
+ ~BindInfo() { dispatcher.info_ = 0; dispatcher.cb_ = 0; }
ParseDispatcher & dispatcher;
};
void beginCommand(std::vector<Token> & command)
- { ParserAccess::init(info_);
- ParserAccess::setCommand(info_, command); }
+ { info_->clear();
+ info_->command(command); }
void endCommand()
- { cb_(info_); }
+ { cb_(*info_); }
void pushToken(Token const & token)
- { ParserAccess::addToken(info_, token); }
+ { info_->addToken(token); }
void builtin_cd(std::vector<Token> & path)
- { ParserAccess::init(info_);
- ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinCD);
+ { info_->clear();
+ info_->builtin(ParseCommandInfo::BuiltinCD);
setBuiltinPathArg(path);
- cb_(info_); }
+ cb_(*info_); }
void builtin_ls(std::vector<Token> & path)
- { ParserAccess::init(info_);
- ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinLS);
+ { info_->clear();
+ info_->builtin(ParseCommandInfo::BuiltinLS);
setBuiltinPathArg(path);
- cb_(info_); }
+ cb_(*info_); }
void pushDirectory(std::vector<Token> & path)
- { ParserAccess::init(info_);
- ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinPUSHD);
+ { info_->clear();
+ info_->builtin(ParseCommandInfo::BuiltinPUSHD);
setBuiltinPathArg(path);
- cb_(info_); }
+ cb_(*info_); }
void popDirectory()
- { ParserAccess::init(info_);
- ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinPOPD);
- cb_(info_); }
+ { info_->clear();
+ info_->builtin(ParseCommandInfo::BuiltinPOPD);
+ cb_(*info_); }
void builtin_exit()
- { ParserAccess::init(info_);
- ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinEXIT);
- cb_(info_); }
+ { info_->clear();
+ info_->builtin(ParseCommandInfo::BuiltinEXIT);
+ cb_(*info_); }
void builtin_help(std::vector<Token> & path)
- { ParserAccess::init(info_);
- ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinHELP);
+ { info_->clear();
+ info_->builtin(ParseCommandInfo::BuiltinHELP);
setBuiltinPathArg(path);
- cb_(info_); }
+ cb_(*info_); }
void setBuiltinPathArg(std::vector<Token> & path)
{
- pushToken(Token(Token::ArgumentGroupOpen, "("));
+ pushToken(ArgumentGroupOpenToken());
for (std::vector<Token>::const_iterator i (path.begin());
i != path.end(); ++i)
pushToken(*i);
- pushToken(Token(Token::ArgumentGroupClose, ")"));
+ pushToken(ArgumentGroupCloseToken());
}
};
prefix_ bool senf::console::CommandParser::parse(std::string command, Callback cb)
{
- detail::ParseDispatcher::BindInfo bind (impl().dispatcher, cb);
+ ParseCommandInfo info;
+ detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info, cb);
return boost::spirit::parse( command.begin(), command.end(),
impl().grammar.use_parser<Impl::Grammar::CommandParser>(),
impl().grammar.use_parser<Impl::Grammar::SkipParser>()
prefix_ bool senf::console::CommandParser::parseFile(std::string filename, Callback cb)
{
- detail::ParseDispatcher::BindInfo bind (impl().dispatcher, cb);
+ ParseCommandInfo info;
+ detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info, cb);
boost::spirit::file_iterator<> i (filename);
if (!i) throw SystemException(ENOENT SENF_EXC_DEBUGINFO);
boost::spirit::file_iterator<> const i_end (i.make_end());
).full;
}
+prefix_ bool senf::console::CommandParser::parseArguments(std::string arguments,
+ ParseCommandInfo & info)
+{
+ detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info, 0);
+ return boost::spirit::parse( arguments.begin(), arguments.end(),
+ impl().grammar.use_parser<Impl::Grammar::ArgumentsParser>(),
+ impl().grammar.use_parser<Impl::Grammar::SkipParser>()
+ ).full;
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "Parse.mpp"
///////////////////////////////////////////////////////////////////////////
// senf::console::ParseCommandInfo
+prefix_ senf::console::ParseCommandInfo::ParseCommandInfo()
+ : builtin_ (NoBuiltin)
+{}
+
prefix_ senf::console::ParseCommandInfo::BuiltinCommand
senf::console::ParseCommandInfo::builtin()
const
return boost::make_iterator_range(tokens_.begin(), tokens_.end());
}
-////////////////////////////////////////
-// private members
-
-prefix_ void senf::console::ParseCommandInfo::init()
+prefix_ void senf::console::ParseCommandInfo::clear()
{
builtin_ = NoBuiltin;
commandPath_.clear();
tokens_.clear();
}
-prefix_ void senf::console::ParseCommandInfo::setBuiltin(BuiltinCommand builtin)
+prefix_ void senf::console::ParseCommandInfo::builtin(BuiltinCommand builtin)
{
builtin_ = builtin;
+ commandPath_.clear();
}
prefix_ void
-senf::console::ParseCommandInfo::setCommand(std::vector<Token> & commandPath)
+senf::console::ParseCommandInfo::command(std::vector<Token> & commandPath)
{
commandPath_.clear();
commandPath_.swap(commandPath);
+ builtin_ = NoBuiltin;
}
prefix_ void senf::console::ParseCommandInfo::addToken(Token const & token)
std::ostream & operator<<(std::ostream & os, Token const & token);
-
Token NoneToken();
Token PathSeparatorToken();
Token ArgumentGroupOpenToken();
BuiltinEXIT,
BuiltinHELP };
+ ParseCommandInfo();
+
BuiltinCommand builtin() const; ///< Command type
/**< \returns \c NoBuiltin, if the command is an ordinary
command, otherwise the id of the built-in command */
TokensRange tokens() const; ///< All argument tokens
/**< The returned range contains \e all argument tokens in a
single range not divided into separate arguments. */
- protected:
- private:
- void init();
- void setBuiltin(BuiltinCommand builtin);
- void setCommand(std::vector<Token> & commandPath);
+ void clear();
+
+ void builtin(BuiltinCommand builtin);
+ void command(std::vector<Token> & commandPath);
+
void addToken(Token const & token);
+ protected:
+
+ private:
struct MakeRange;
std::vector<Token> commandPath_;
BuiltinCommand builtin_;
Tokens tokens_;
-
- friend class detail::ParserAccess;
};
/** \brief Iterator parsing argument groups
/**< \throws SystemException if the file cannot be
read. */
+ bool parseArguments(std::string arguments, ParseCommandInfo & info);
+
private:
struct Impl;
///////////////////////////////////////////////////////////////////////////
// Start rules
- enum { CommandParser, SkipParser };
+ enum { CommandParser, SkipParser, ArgumentsParser };
///////////////////////////////////////////////////////////////////////////
// The parse context (variables needed while parsing)
template <class Scanner>
struct definition
: public boost::spirit::grammar_def< boost::spirit::rule<Scanner>,
+ boost::spirit::rule<Scanner>,
boost::spirit::rule<Scanner> >
{
boost::spirit::rule<Scanner> command, path, argument, word, string, hexstring, token,
punctuation, hexbyte, balanced_tokens, simple_argument, complex_argument, builtin,
- skip, commands, block, statement, relpath, abspath;
+ skip, commands, block, statement, relpath, abspath, arguments;
boost::spirit::chset<> special_p, punctuation_p, space_p, invalid_p, word_p;
boost::spirit::distinct_parser<> keyword_p;
statement
= eps_p [ self.dispatch(&PD::beginCommand,
boost::ref(self.context.path)) ]
- >> * argument
+ >> arguments
>> (ch_p(';') | end_p)
>> eps_p [ self.dispatch(&PD::endCommand) ]
;
+ arguments
+ = * argument
+ ;
+
argument
= simple_argument [ self.dispatch(&PD::pushToken,
boost::ref(self.context.token)) ]
start_parsers(
commands, // CommandParser
- skip // SkipParser
+ skip, // SkipParser
+ arguments // ArgumentsParser
);
BOOST_SPIRIT_DEBUG_TRACE_RULE(command,1);
--- /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 ProgramOptions non-inline non-template implementation */
+
+#include "ProgramOptions.hh"
+#include "ProgramOptions.ih"
+
+// Custom includes
+#include <boost/algorithm/string/predicate.hpp>
+
+//#include "ProgramOptions.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ProgramOptionsSource
+
+prefix_ void senf::console::detail::ProgramOptionsSource::v_parse(RestrictedExecutor & executor)
+{
+ char ** argp (argv_);
+ int n (argc_);
+ for (; n; --n, ++argp) {
+ std::string arg (*argp);
+ if (boost::algorithm::starts_with(arg, std::string("--")))
+ parseLongOption(arg.substr(2), executor);
+ else
+ parseNonOption(arg, executor);
+ }
+}
+
+namespace {
+ struct MakeWordToken
+ {
+ typedef senf::console::Token result_type;
+ template <class Range>
+ result_type operator()(Range const & r) const
+ { return senf::console::WordToken(std::string(boost::begin(r), boost::end(r))); }
+ };
+}
+
+prefix_ void
+senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & arg,
+ RestrictedExecutor & executor)
+{
+ std::string::size_type ix (arg.find('='));
+ std::string name (arg.substr(0,ix));
+ std::string value (ix==std::string::npos ? std::string() : arg.substr(ix+1));
+
+ typedef std::vector<Token> Path;
+
+ ParseCommandInfo cmd;
+ Path path;
+
+ DirectoryNode::ptr cwd (executor.root().thisptr());
+ std::string::size_type b (0);
+ while (b < name.size()) {
+ std::string::size_type e (name.size());
+ for (;e != std::string::npos && e > b; e = name.rfind('-', e)) {
+ DirectoryNode::ChildrenRange completions (cwd->completions(name.substr(b,e-b)));
+ if (completions.size() == 1) {
+ path.push_back(WordToken(completions.begin()->first));
+ if (e < name.size())
+ cwd = cwd->getDirectory(completions.begin()->first).thisptr();
+ b = e+1;
+ e = b+1;
+ break;
+ }
+ }
+ if (e == std::string::npos || e <= b) {
+ // This will produce a correct error message later
+ path.push_back(WordToken(name.substr(b)));
+ b = name.size();
+ }
+ }
+
+ cmd.command(path);
+ parser_.parseArguments(value, cmd);
+ executor(std::cerr, cmd);
+}
+
+prefix_ void
+senf::console::detail::ProgramOptionsSource::parseNonOption(std::string const & arg,
+ RestrictedExecutor & executor)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ void senf::console::parseOptions(int argc, char ** argv, DirectoryNode & root)
+{
+ ProgramOptions opts (argc, argv, root);
+ opts.parse();
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "ProgramOptions.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 ProgramOptions inline non-template implementation */
+
+#include "ProgramOptions.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ProgramOptionsSource
+
+prefix_ senf::console::detail::ProgramOptionsSource::ptr
+senf::console::detail::ProgramOptionsSource::create(int argc, char ** argv)
+{
+ return ptr(new ProgramOptionsSource(argc,argv));
+}
+
+prefix_ senf::console::detail::ProgramOptionsSource::ProgramOptionsSource(int argc,
+ char ** argv)
+ : argc_ (argc), argv_ (argv)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ProgramOptions
+
+prefix_ senf::console::ProgramOptions::ProgramOptions(int argc, char ** argv,
+ DirectoryNode & root)
+ : detail::BundleMixin (root)
+{
+ add(detail::ProgramOptionsSource::create(argc, argv));
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ senf::console::detail::ProgramOptionsSource::ptr
+senf::console::OptionsConfig(int argc, char ** argv)
+{
+ return detail::ProgramOptionsSource::create(argc, argv);
+}
+
+///////////////////////////////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 ProgramOptions public header */
+
+#ifndef HH_ProgramOptions_
+#define HH_ProgramOptions_ 1
+
+// Custom includes
+#include "Config.hh"
+
+
+//#include "ProgramOptions.mpp"
+#include "ProgramOptions.ih"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+
+ class ProgramOptions
+ : public detail::BundleMixin
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ ProgramOptions(int argc, char ** argv, DirectoryNode & root = root());
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+ };
+
+ void parseOptions(int argc, char ** argv, DirectoryNode & root = root());
+
+ detail::ProgramOptionsSource::ptr OptionsConfig(int argc, char ** argv);
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "ProgramOptions.cci"
+//#include "ProgramOptions.ct"
+//#include "ProgramOptions.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 ProgramOptions internal header */
+
+#ifndef IH_ProgramOptions_
+#define IH_ProgramOptions_ 1
+
+// Custom includes
+#include "Parse.hh"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+ class ProgramOptionsSource : public ConfigSource
+ {
+ public:
+ static ptr create(int argc, char ** argv);
+
+ private:
+ ProgramOptionsSource(int argc, char ** argv);
+
+ virtual void v_parse(RestrictedExecutor & executor);
+
+ void parseLongOption(std::string const & arg, RestrictedExecutor & executor);
+ void parseNonOption(std::string const & arg, RestrictedExecutor & executor);
+
+ int argc_;
+ char ** argv_;
+ CommandParser parser_;
+ };
+
+}}}
+
+///////////////////////////////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 ProgramOptions.test unit tests */
+
+//#include "ProgramOptions.test.hh"
+//#include "ProgramOptions.test.ih"
+
+// Custom includes
+#include "ProgramOptions.hh"
+#include "ScopedDirectory.hh"
+#include "ParsedCommand.hh"
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+ std::string val1;
+ bool val2 (false);
+
+ void fun1(std::string p)
+ { val1 = p; }
+
+ void fun2()
+ { val2 = true; }
+}
+
+BOOST_AUTO_UNIT_TEST(programOptions)
+{
+ senf::console::ScopedDirectory<> root;
+ senf::console::root().add("root", root);
+
+ root.mkdir("dir1").add("fun1", &fun1);
+ root.add("fun2", &fun2);
+ root.mkdir("name-with-dashes").add("fun-2", &fun2);
+
+ {
+ char * argv[] = { "--dir1-fun1=foo","--fun2" };
+ senf::console::ProgramOptions opts (sizeof(argv)/sizeof(argv[0]), argv, root);
+
+ SENF_CHECK_NO_THROW( opts.parse() );
+ BOOST_CHECK_EQUAL( val1, "foo" );
+ BOOST_CHECK_EQUAL( val2, true );
+ }
+
+ {
+ char * argv[] = { "--d-f=foo","--fun" };
+ senf::console::ProgramOptions opts (sizeof(argv)/sizeof(argv[0]), argv, root);
+
+ val1 = "";
+ val2 = false;
+
+ SENF_CHECK_NO_THROW( opts.parse() );
+ BOOST_CHECK_EQUAL( val1, "foo" );
+ BOOST_CHECK_EQUAL( val2, true );
+ }
+
+ {
+ char * argv[] = { "--name-w-fun" };
+ senf::console::ProgramOptions opts (sizeof(argv)/sizeof(argv[0]), argv, root);
+
+ val1 = "";
+ val2 = false;
+
+ SENF_CHECK_NO_THROW( opts.parse() );
+ BOOST_CHECK_EQUAL( val1, "" );
+ BOOST_CHECK_EQUAL( val2, true );
+ }
+}
+
+///////////////////////////////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: