Missing changes from last commit
g0dil [Sat, 17 May 2008 11:51:58 +0000 (11:51 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@846 270642c3-0616-0410-b53a-bc976706d245

14 files changed:
Console/Config.cc [new file with mode: 0644]
Console/Config.cci [new file with mode: 0644]
Console/Config.hh [new file with mode: 0644]
Console/Config.test.cc [new file with mode: 0644]
Console/Console.hh
Console/Executor.cc
Console/Executor.cci
Console/Executor.hh
Console/Server.cc
Console/Server.hh
SConstruct
Scheduler/Scheduler.cc
Scheduler/Scheduler.hh
Utils/auto_unit_test.hh

diff --git a/Console/Config.cc b/Console/Config.cc
new file mode 100644 (file)
index 0000000..15d3cc5
--- /dev/null
@@ -0,0 +1,75 @@
+// $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 non-inline non-template implementation */
+
+#include "Config.hh"
+//#include "Config.ih"
+
+// Custom includes
+
+//#include "Config.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ConfigFile
+
+prefix_ void senf::console::ConfigFile::parse()
+{
+    if (! parser_.parseFile(filename_, boost::bind<void>( boost::ref(executor_),
+                                                          boost::ref(std::cerr),
+                                                          _1 )) )
+        throw SyntaxErrorException();
+}
+
+prefix_ void senf::console::ConfigFile::parse(DirectoryNode & restrict)
+{
+    restrict_ = restrict.thisptr();
+    parse();
+    parsedNodes_.push_back(restrict_);
+    restrict_.reset();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ void senf::console::readConfig(std::string const & filename)
+{
+    ConfigFile cfg (filename);
+    cfg.parse();
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Config.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:
diff --git a/Console/Config.cci b/Console/Config.cci
new file mode 100644 (file)
index 0000000..f4e42bc
--- /dev/null
@@ -0,0 +1,78 @@
+// $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 inline non-template implementation */
+
+//#include "Config.ih"
+
+// Custom includes
+#include "../Utils/membind.hh"
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ConfigFile
+
+prefix_ senf::console::ConfigFile::ConfigFile(std::string const & filename)
+    : filename_ (filename)
+{
+    executor_.policy(senf::membind(&ConfigFile::policyCallback, this));
+}
+
+prefix_ void senf::console::ConfigFile::policyCallback(DirectoryNode & dir,
+                                                       std::string const & name)
+{
+    if (dir.hasChild(name)) {
+        GenericNode & item (dir.get(name));
+        if (restrict_ && ! item.isChildOf(*restrict_)) {
+            DirectoryNode * itemdir (dynamic_cast<DirectoryNode*>(&item));
+            if (! itemdir || ! restrict_->isChildOf(*itemdir))
+                throw Executor::IgnoreCommandException();
+        }
+        ParsedNodes::const_iterator i (parsedNodes_.begin());
+        ParsedNodes::const_iterator const i_end (parsedNodes_.end());
+        for (; i != i_end; ++i) {
+            if ( ! i->expired() && item.isChildOf(*(i->lock())) )
+                throw Executor::IgnoreCommandException();
+        }
+    }
+    else {
+        if (restrict_ && ! dir.isChildOf(*restrict_))
+            throw Executor::IgnoreCommandException();
+    }
+}
+
+///////////////////////////////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:
diff --git a/Console/Config.hh b/Console/Config.hh
new file mode 100644 (file)
index 0000000..ce74973
--- /dev/null
@@ -0,0 +1,92 @@
+// $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 public header */
+
+#ifndef HH_Console_Config_
+#define HH_Console_Config_ 1
+
+// Custom includes
+#include <boost/utility.hpp>
+#include "Parse.hh"
+#include "Executor.hh"
+
+//#include "Config.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+
+    /** \brief
+      */
+    class ConfigFile
+        : boost::noncopyable
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        explicit ConfigFile(std::string const & filename);
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void parse();
+        void parse(DirectoryNode & restrict);
+
+    protected:
+
+    private:
+        void policyCallback(DirectoryNode & dir, std::string const & item);
+
+        typedef std::vector<DirectoryNode::weak_ptr> ParsedNodes;
+
+        std::string filename_;
+        CommandParser parser_;
+        Executor executor_;
+
+        DirectoryNode::ptr restrict_;
+        ParsedNodes parsedNodes_;
+    };
+
+    void readConfig(std::string const & filename);
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Config.cci"
+//#include "Config.ct"
+//#include "Config.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:
diff --git a/Console/Config.test.cc b/Console/Config.test.cc
new file mode 100644 (file)
index 0000000..df5c070
--- /dev/null
@@ -0,0 +1,168 @@
+// $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.test unit tests */
+
+//#include "Config.test.hh"
+//#include "Config.test.ih"
+
+// Custom includes
+#include "Config.hh"
+#include <fstream>
+#include "ScopedDirectory.hh"
+#include "ParsedCommand.hh"
+#include <boost/filesystem/operations.hpp>
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+    int var1 (0);
+    bool var2 (false);
+    
+    void fun1(int v) { var1 = v; }
+    void fun2() { var2 = true; }
+
+    class TempFile
+    {
+    public:
+        TempFile(std::string const & name) : name_ (name), file_ (name_.c_str()) {}
+        ~TempFile() { file_.close(); boost::filesystem::remove(name_); }
+        
+        template <class T> TempFile & operator<<(T const & v) { file_ << v; return *this; }
+        enum Closer { close }; void operator<<(Closer) { file_.close(); }
+        std::string const & name() { return name_; }
+
+    private:
+        std::string name_;
+        std::ofstream file_;
+    };
+
+    
+}
+
+BOOST_AUTO_UNIT_TEST(configFile)
+{
+    TempFile cfgf ("test.cfg");
+    cfgf << "dir1/fun1 10;\n" 
+         << TempFile::close;
+    
+    senf::console::ScopedDirectory<> dir1;
+    senf::console::root().add("dir1", dir1);
+    dir1.add("fun1",&fun1);
+
+    {
+        var1 = 0;
+        senf::console::ConfigFile cfg (cfgf.name());
+        SENF_CHECK_NO_THROW( cfg.parse() )
+        BOOST_CHECK_EQUAL( var1, 10 );
+    }
+}
+
+BOOST_AUTO_UNIT_TEST(configFileRestrict)
+{
+    TempFile cfgf ("test.cfg");
+    cfgf << "dir1/fun1 10;\n"
+         << "dir2/fun2;\n"
+         << TempFile::close;
+    
+    senf::console::ScopedDirectory<> dir1;
+    senf::console::root().add("dir1", dir1);
+    dir1.add("fun1",&fun1);
+    
+    {
+        var1 = 0;
+        var2 = false;
+        senf::console::ConfigFile cfg (cfgf.name());
+        SENF_CHECK_NO_THROW( cfg.parse(dir1.node()) );
+        BOOST_CHECK_EQUAL( var1, 10 );
+        BOOST_CHECK_EQUAL( var2, false );
+
+        senf::console::ScopedDirectory<> dir2;
+        senf::console::root().add("dir2", dir2);
+        dir2.add("fun2",&fun2);
+
+        var1 = 0;
+        var2 = false;
+        SENF_CHECK_NO_THROW( cfg.parse() );
+        BOOST_CHECK_EQUAL( var1, 0 );
+        BOOST_CHECK_EQUAL( var2, true );
+    }
+}
+
+BOOST_AUTO_UNIT_TEST(configFileSkipGroup)
+{
+    TempFile cfgf ("test.cfg");
+    cfgf << "dir1/fun1 10;\n"
+         << "dir2 { dir3 { fun2; } fun1 5; }"
+         << TempFile::close;
+    
+    senf::console::ScopedDirectory<> dir1;
+    senf::console::root().add("dir1", dir1);
+    dir1.add("fun1",&fun1);
+    
+    senf::console::ScopedDirectory<> dir2;
+    senf::console::root().add("dir2", dir2);
+    
+    dir2.mkdir("dir3").add("fun2", &fun2);
+    dir2.add("fun1", &fun1);
+
+    {
+        var1 = 0;
+        var2 = false;
+        senf::console::ConfigFile cfg (cfgf.name());
+        SENF_CHECK_NO_THROW( cfg.parse(dir1.node()) );
+        BOOST_CHECK_EQUAL( var1, 10 );
+        BOOST_CHECK_EQUAL( var2, false );
+
+        var1 = 0;
+        var2 = false;
+        SENF_CHECK_NO_THROW( cfg.parse(dir2["dir3"]) );
+        BOOST_CHECK_EQUAL( var1, 0 );
+        BOOST_CHECK_EQUAL( var2, true );
+
+        var1 = 0;
+        var2 = false;
+        SENF_CHECK_NO_THROW( cfg.parse() );
+        BOOST_CHECK_EQUAL( var1, 5 );
+        BOOST_CHECK_EQUAL( var2, false );
+    }
+}
+
+///////////////////////////////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:
index 88149ed..9b1d339 100644 (file)
@@ -34,6 +34,7 @@
 #include "Server.hh"
 #include "ParsedCommand.hh"
 #include "ScopedDirectory.hh"
+#include "Config.hh"
 
 ///////////////////////////////hh.e////////////////////////////////////////
 //#include "Console.cci"
index 3533a0e..3a8c228 100644 (file)
@@ -57,6 +57,8 @@ prefix_ void senf::console::Executor::execute(std::ostream & output,
     try {
         switch(command.builtin()) {
         case ParseCommandInfo::NoBuiltin : {
+            if (skipping_)
+                break;
             GenericNode & node ( traverseCommand(command.commandPath()) );
             DirectoryNode * dir ( dynamic_cast<DirectoryNode*>(&node) );
             if ( dir ) {
@@ -72,23 +74,33 @@ prefix_ void senf::console::Executor::execute(std::ostream & output,
         }
 
         case ParseCommandInfo::BuiltinCD :
-            if ( command.arguments() ) {
-                if (command.arguments().begin()->size() == 1 
-                    && command.arguments().begin()->begin()->value() == "-") {
-                    if (oldCwd_.expired() || ! oldCwd_.lock()->active()) {
+            if (skipping_)
+                break;
+            try {
+                if ( command.arguments() ) {
+                    if (command.arguments().begin()->size() == 1 
+                        && command.arguments().begin()->begin()->value() == "-") {
+                        if (oldCwd_.expired() || ! oldCwd_.lock()->active()) {
+                            oldCwd_ = cwd_;
+                            cwd_ = root_;
+                        } else
+                            swap(cwd_, oldCwd_);
+                    }
+                    else {
                         oldCwd_ = cwd_;
-                        cwd_ = root_;
-                    } else
-                        swap(cwd_, oldCwd_);
-                }
-                else {
-                    oldCwd_ = cwd_;
                     cwd_ = traverseDirectory(*command.arguments().begin()).thisptr();
+                    }
                 }
             }
+            catch (IgnoreCommandException &) {
+                throw SyntaxErrorException(
+                    "'cd' cannot be skipped (don't use 'cd' in conf-files)");
+            }
             break;
             
         case ParseCommandInfo::BuiltinLS : {
+            if (skipping_)
+                break;
             DirectoryNode const & dir ( command.arguments()
                                         ? traverseDirectory(*command.arguments().begin())
                                         : cwd() );
@@ -103,22 +115,34 @@ prefix_ void senf::console::Executor::execute(std::ostream & output,
         }
 
         case ParseCommandInfo::BuiltinPUSHD :
-            dirstack_.push_back(cwd_);
-            if ( command.arguments() )
-                cwd_ = traverseDirectory(*command.arguments().begin()).thisptr();
+            dirstack_.push_back(DirEntry(cwd_, skipping_));
+            if ( ! skipping_ && command.arguments() ) {
+                try {
+                    cwd_ = traverseDirectory(*command.arguments().begin()).thisptr();
+                }
+                catch (IgnoreCommandException &) {
+                    cwd_.reset();
+                    skipping_ = true;
+                }
+            }
             break;
             
         case ParseCommandInfo::BuiltinPOPD :
             if (! dirstack_.empty()) {
-                cwd_ = dirstack_.back();
+                cwd_ = dirstack_.back().dir;
+                skipping_ = dirstack_.back().skip;
                 dirstack_.pop_back();
             }
             break;
             
         case ParseCommandInfo::BuiltinEXIT :
+            if (skipping_)
+                break;
             throw ExitException();
 
         case ParseCommandInfo::BuiltinHELP :
+            if (skipping_)
+                break;
             GenericNode const & node (command.arguments() 
                                       ? traverseNode(*command.arguments().begin())
                                       : cwd());
index 744737e..ab91c30 100644 (file)
@@ -35,7 +35,7 @@
 
 prefix_ senf::console::Executor::Executor()
     : root_(senf::console::root().thisptr()), cwd_ (root_), oldCwd_ (cwd_),
-      autocd_ (false), autocomplete_ (false)
+      autocd_ (false), autocomplete_ (false), skipping_ (false)
 {}
 
 prefix_ void senf::console::Executor::operator()(std::ostream & output,
index e126590..5cdd1f7 100644 (file)
@@ -142,11 +142,18 @@ namespace console {
         SecurityPolicy policy_;
         DirectoryNode::weak_ptr cwd_;
         DirectoryNode::weak_ptr oldCwd_;
-        typedef std::vector<DirectoryNode::weak_ptr> DirStack;
+        struct DirEntry {
+            DirEntry(DirectoryNode::weak_ptr dir_, bool skip_) : dir(dir_), skip(skip_) {}
+            DirectoryNode::weak_ptr dir;
+            bool skip;
+        };
+        typedef std::vector<DirEntry> DirStack;
         DirStack dirstack_;
 
         bool autocd_;
         bool autocomplete_;
+        
+        bool skipping_;
     };
 
 
index 64b669e..eecc1d6 100644 (file)
@@ -236,7 +236,7 @@ prefix_ void senf::console::Client::handleInput(std::string data)
     }
 }
 
-prefix_ void senf::console::Client::v_write(boost::posix_time::ptime timestamp,
+prefix_ void senf::console::Client::v_write(senf::log::time_type timestamp,
                                             std::string const & stream,
                                             std::string const & area, unsigned level,
                                             std::string const & message)
index be3dd6c..d43a6d1 100644 (file)
@@ -148,7 +148,7 @@ namespace console {
 
         void translate(std::string & data);
         void handleInput(std::string input);
-        virtual void v_write(boost::posix_time::ptime timestamp, std::string const & stream, 
+        virtual void v_write(senf::log::time_type timestamp, std::string const & stream, 
                              std::string const & area, unsigned level, 
                              std::string const & message);
         
index 88dd14f..fce3c2d 100644 (file)
@@ -157,7 +157,7 @@ env.Append(
    CONFIG_FILES_OPTS = configFilesOpts,
    CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign', '.sconsign.dblite' ],
    BUILDPACKAGE_COMMAND = "dpkg-buildpackage -us -uc -rfakeroot -I.svn -I_templates $CONFIG_FILES_OPTS",
-   TOP_INCLUDES = [ 'Packets', 'PPI', 'Scheduler', 'Socket', 'Utils',
+   TOP_INCLUDES = [ 'Packets', 'PPI', 'Scheduler', 'Socket', 'Utils', 'Console',
                     'config.hh', 'local_config.hh' ],
 )
 
@@ -169,7 +169,7 @@ Export('env')
 
 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
 # Create it even when cleaning, to silence the doxygen builder warnings
-if not os.path.exists("Doxyfile.local"):
+if not env.GetOption('clean') and not os.path.exists("Doxyfile.local"):
     Execute(Touch("Doxyfile.local"))
 
 # Create local_config.h
@@ -222,10 +222,11 @@ env.Alias('default', libsenf)
 
 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
 
-env.Clean('all', [ os.path.join(path,f)
-                   for path, subdirs, files in os.walk('.')
-                   for pattern in env['CLEAN_PATTERNS']
-                   for f in fnmatch.filter(files,pattern) ])
+if env.GetOption('clean'):
+    env.Clean('all', [ os.path.join(path,f)
+                       for path, subdirs, files in os.walk('.')
+                       for pattern in env['CLEAN_PATTERNS']
+                       for f in fnmatch.filter(files,pattern) ])
 
 PhonyTarget(env, 'deb', [
     checkLocalConf,
index 1c78fa4..3d61946 100644 (file)
@@ -341,10 +341,10 @@ prefix_ void senf::Scheduler::process()
 ///////////////////////////////////////////////////////////////////////////
 // senf::SchedulerLogTimeSource
 
-prefix_ boost::posix_time::ptime senf::SchedulerLogTimeSource::operator()()
+prefix_ senf::log::time_type senf::SchedulerLogTimeSource::operator()()
     const
 {
-    return ClockService::abstime(Scheduler::instance().eventTime());
+    return Scheduler::instance().eventTime();
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index 0d51c35..4869e8f 100644 (file)
@@ -430,7 +430,7 @@ namespace senf {
      */
     struct SchedulerLogTimeSource : public senf::log::TimeSource
     {
-        boost::posix_time::ptime operator()() const;
+        senf::log::time_type operator()() const;
     };
 
 }
index c45d6fd..a126692 100644 (file)
 
 #define COMPILE_FAIL(n) void n()
 
+#define SENF_CHECK_NO_THROW(expr)                                                                 \
+    BOOST_CHECK_NO_THROW(                                                                         \
+        try { (void) expr ; }                                                                     \
+        catch (std::exception & e) { std::cerr << e.what() << std::endl; throw; } )
+
 ///////////////////////////////hh.e////////////////////////////////////////
 //#include "auto_unit_test.cci"
 //#include "auto_unit_test.ct"