From d2d8d5de07eae139025bf383138037b0e8952df3 Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Fri, 16 Jan 2009 22:24:01 +0000
Subject: [PATCH] Utils: Add ScopeExit class Utils/Console: Add '@' to 'ls'
 output for link nodes Utils/Console: Path completion in the LineEditor
 follows links in all cases Utils/Console: Path completion adds blank space
 after non-directories

---
 Scheduler/FIFORunner.cc     | 49 +++++++++++++--------------
 Scheduler/Scheduler.cc      | 53 +++++++++++++++++------------
 Utils/Console/Executor.cc   |  4 ++-
 Utils/Console/LineEditor.cc | 11 +++---
 Utils/Console/Node.cci      | 20 ++++++++---
 Utils/Console/Node.hh       | 13 ++++---
 Utils/Console/testServer.cc |  4 +++
 Utils/ScopeExit.cci         | 54 ++++++++++++++++++++++++++++++
 Utils/ScopeExit.hh          | 67 +++++++++++++++++++++++++++++++++++++
 Utils/Termlib/Editor.cc     |  4 +--
 10 files changed, 215 insertions(+), 64 deletions(-)
 create mode 100644 Utils/ScopeExit.cci
 create mode 100644 Utils/ScopeExit.hh

diff --git a/Scheduler/FIFORunner.cc b/Scheduler/FIFORunner.cc
index 545b4ae20..b39b5c2fe 100644
--- a/Scheduler/FIFORunner.cc
+++ b/Scheduler/FIFORunner.cc
@@ -29,8 +29,10 @@
 // Custom includes
 #include <signal.h>
 #include <time.h>
+#include <boost/lambda/lambda.hpp>
 #include "../Utils/Exception.hh"
 #include "../Utils/senfassert.hh"
+#include "../Utils/ScopeExit.hh"
 
 //#include "FIFORunner.mpp"
 #define prefix_
@@ -143,7 +145,6 @@ prefix_ void senf::scheduler::detail::FIFORunner::run()
     run(f, l);
 }
 
-
 prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, TaskList::iterator l)
 {
     if (f == l)
@@ -164,32 +165,30 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task
     tasks_.insert(l, null);
     TaskList::iterator end (TaskList::current(null));
     next_ = f;
-    try {
-        while (next_ != end) {
-            TaskInfo & task (*next_);
-            if (task.runnable_) {
-                task.runnable_ = false;
-                runningName_ = task.name();
-#           ifdef SENF_DEBUG
-                runningBacktrace_ = task.backtrace_;
-#           endif
-                TaskList::iterator i (next_);
-                ++ next_;
-                tasks_.splice(l, tasks_, i);
-                watchdogCount_ = 1;
-                task.run();
-            }
-            else
-                ++ next_;
+
+    using namespace boost::lambda;
+    ScopeExit atExit ((
+                          var(watchdogCount_) = 0, 
+                          var(next_) = l
+                          ));
+    
+    while (next_ != end) {
+        TaskInfo & task (*next_);
+        if (task.runnable_) {
+            task.runnable_ = false;
+            runningName_ = task.name();
+#       ifdef SENF_DEBUG
+            runningBacktrace_ = task.backtrace_;
+#       endif
+            TaskList::iterator i (next_);
+            ++ next_;
+            tasks_.splice(l, tasks_, i);
+            watchdogCount_ = 1;
+            task.run();
         }
+        else
+            ++ next_;
     }
-    catch (...) {
-        watchdogCount_ = 0;
-        next_ = l;
-        throw;
-    }
-    watchdogCount_ = 0;
-    next_ = l;
 }
 
 prefix_ senf::scheduler::detail::FIFORunner::TaskList::iterator
diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc
index e7550bb0a..246745936 100644
--- a/Scheduler/Scheduler.cc
+++ b/Scheduler/Scheduler.cc
@@ -48,31 +48,40 @@ prefix_ void senf::scheduler::terminate()
     terminate_ = true;
 }
 
+namespace {
+    
+    // We don't want try { } catch(...) { ... throw; } since that will make debugging more
+    // difficult: the stack backtrace for an unexpected exception would always end here.
+    struct SchedulerScopedInit
+    {
+        SchedulerScopedInit() 
+            {
+                senf::scheduler::detail::FIFORunner::instance().startWatchdog();
+                senf::scheduler::detail::SignalDispatcher::instance().unblockSignals();
+                senf::scheduler::detail::TimerDispatcher::instance().unblockSignals();
+            }
+
+        ~SchedulerScopedInit()
+            {
+                senf::scheduler::detail::TimerDispatcher::instance().blockSignals();
+                senf::scheduler::detail::SignalDispatcher::instance().blockSignals();
+                senf::scheduler::detail::FIFORunner::instance().stopWatchdog();
+            }
+    };
+}
+
 prefix_ void senf::scheduler::process()
 {
-    try {
-        detail::FIFORunner::instance().startWatchdog();
-        detail::SignalDispatcher::instance().unblockSignals();
-        detail::TimerDispatcher::instance().unblockSignals();
-        terminate_ = false;
-        while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
-                                 detail::TimerDispatcher::instance().empty() &&
-                                 detail::FileDispatcher::instance().empty())) {
-            detail::FdManager::instance().processOnce();
-            detail::FileDispatcher::instance().prepareRun();
-            detail::EventHookDispatcher::instance().prepareRun();
-            detail::FIFORunner::instance().run();
-        }
-    }
-    catch(...) {
-        detail::TimerDispatcher::instance().blockSignals();
-        detail::SignalDispatcher::instance().blockSignals();
-        detail::FIFORunner::instance().stopWatchdog();
-        throw;
+    SchedulerScopedInit initScheduler;
+    terminate_ = false;
+    while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
+                             detail::TimerDispatcher::instance().empty() &&
+                             detail::FileDispatcher::instance().empty())) {
+        detail::FdManager::instance().processOnce();
+        detail::FileDispatcher::instance().prepareRun();
+        detail::EventHookDispatcher::instance().prepareRun();
+        detail::FIFORunner::instance().run();
     }
-    detail::TimerDispatcher::instance().blockSignals();
-    detail::SignalDispatcher::instance().blockSignals();
-    detail::FIFORunner::instance().stopWatchdog();
 }
 
 prefix_ void senf::scheduler::restart()
diff --git a/Utils/Console/Executor.cc b/Utils/Console/Executor.cc
index f78a73688..04cb75101 100644
--- a/Utils/Console/Executor.cc
+++ b/Utils/Console/Executor.cc
@@ -194,8 +194,10 @@ prefix_ void senf::console::Executor::ls(std::ostream & output,
     DirectoryNode::child_iterator const i_end (node.children().end());
     for (; i != i_end; ++i) {
         output << i->first;
-        if (boost::dynamic_pointer_cast<DirectoryNode>(i->second))
+        if (i->second->isDirectory())
             output << "/";
+        else if (i->second->isLink())
+            output << "@";
         output << "\n";
     }
 }
diff --git a/Utils/Console/LineEditor.cc b/Utils/Console/LineEditor.cc
index bf4d86936..31df1f782 100644
--- a/Utils/Console/LineEditor.cc
+++ b/Utils/Console/LineEditor.cc
@@ -145,7 +145,7 @@ completePath(term::LineEditor & editor, unsigned b, unsigned e,
     if (path.empty()) {
         DirectoryNode::ChildrenRange cs (client().cwd().children());
         for (DirectoryNode::ChildrenRange::iterator i (cs.begin()); i != cs.end(); ++i)
-            completions.push_back(i->first + (i->second->isDirectory() ? "/" : ""));
+            completions.push_back(i->first + (i->second->followLink().isDirectory() ? "/" : " "));
         return;
     }
     
@@ -180,10 +180,10 @@ completePath(term::LineEditor & editor, unsigned b, unsigned e,
             else {
                 DirectoryNode::ChildrenRange cs (dir->completions(i->value()));
                 if (has_one_elt(cs)) {
-                    GenericNode * node (cs.begin()->second.get());
-                    if (!node->isDirectory())
+                    GenericNode & node (cs.begin()->second->followLink());
+                    if (!node.isDirectory())
                         return;
-                    dir = static_cast<DirectoryNode*>(node);
+                    dir = static_cast<DirectoryNode*>(&node);
                     basePath += cs.begin()->first + "/";
                 }
                 else
@@ -193,7 +193,8 @@ completePath(term::LineEditor & editor, unsigned b, unsigned e,
 
     DirectoryNode::ChildrenRange cs (dir->completions(i->value()));
     for (DirectoryNode::ChildrenRange::iterator j (cs.begin()); j != cs.end(); ++j)
-        completions.push_back(basePath + j->first + (j->second->isDirectory() ? "/" : ""));
+        completions.push_back(basePath + j->first 
+                              + (j->second->followLink().isDirectory() ? "/" : " "));
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
diff --git a/Utils/Console/Node.cci b/Utils/Console/Node.cci
index dabaec9b1..1c130cbdf 100644
--- a/Utils/Console/Node.cci
+++ b/Utils/Console/Node.cci
@@ -114,6 +114,21 @@ prefix_ bool senf::console::GenericNode::isCommand()
     return dynamic_cast<CommandNode const *>(this);
 }
 
+prefix_ senf::console::GenericNode const & senf::console::GenericNode::followLink()
+    const
+{
+    return isLink()
+        ? dynamic_cast<LinkNode const *>(this)->follow()
+        : *this;
+}
+
+prefix_ senf::console::GenericNode & senf::console::GenericNode::followLink()
+{
+    return isLink()
+        ? dynamic_cast<LinkNode *>(this)->follow()
+        : *this;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::LinkNode
 
@@ -154,10 +169,7 @@ prefix_ senf::console::GenericNode &
 senf::console::DirectoryNode::get(std::string const & name)
     const
 {
-    GenericNode & node (getLink(name));
-    return node.isLink()
-        ? dynamic_cast<LinkNode&>(node).follow()
-        : node;
+    return getLink(name).followLink();
 }
 
 prefix_ senf::console::DirectoryNode &
diff --git a/Utils/Console/Node.hh b/Utils/Console/Node.hh
index 137c8b018..6caef9621 100644
--- a/Utils/Console/Node.hh
+++ b/Utils/Console/Node.hh
@@ -296,6 +296,9 @@ namespace console {
         bool isLink() const;            ///< \c true, if this is a link node
         bool isCommand() const;         ///< \c true, if this is a command node
 
+        GenericNode const & followLink() const; ///< Follow link if \c this node is a link node
+        GenericNode & followLink();     ///< Follow link if \c this node is a link node
+
     protected:
         GenericNode();
 
@@ -491,7 +494,7 @@ namespace console {
                                         ///< \c true, if there is a child with name \a name
 
         GenericNode & get(std::string const & name) const;
-                                        ///< Get child node
+                                        ///< Get child node automatically dereferencing links
                                         /**< \throws UnknownNodeNameException if a child \a name
                                                  does not exist */
         GenericNode & getLink(std::string const & name) const;
@@ -500,7 +503,7 @@ namespace console {
                                                  does not exist */
 
         DirectoryNode & getDirectory(std::string const & name) const;
-                                        ///< Get directory child node
+                                        ///< Get directory child node (dereferencing links)
                                         /**< Same as operator[]
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist.
@@ -508,7 +511,7 @@ namespace console {
                                                  directory node. */
 
         DirectoryNode & operator[](std::string const & name) const;
-                                        ///< Get directory child node
+                                        ///< Get directory child node (dereferencing links)
                                         /**< Same as getDirectory
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist.
@@ -516,7 +519,7 @@ namespace console {
                                                  directory node. */
 
         CommandNode & getCommand(std::string const & name) const;
-                                        ///< Get command child node
+                                        ///< Get command child node (dereferencing links)
                                         /**< Same as operator()
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist
@@ -524,7 +527,7 @@ namespace console {
                                                  command node. */
 
         CommandNode & operator()(std::string const & name) const;
-                                        ///< Get command child node
+                                        ///< Get command child node (dereferencing links)
                                         /**< Same as getCommand()
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist
diff --git a/Utils/Console/testServer.cc b/Utils/Console/testServer.cc
index 74580557f..5d1a323c6 100644
--- a/Utils/Console/testServer.cc
+++ b/Utils/Console/testServer.cc
@@ -97,6 +97,8 @@ int main(int, char **)
         .add("showlog", &enableLogging)
         .doc("Enable display of log messages on the current console");
 
+    senf::console::root().link("sl", senf::console::root()["console"]("showlog"));
+
     serverDir
         .add("shutdown", &shutdownServer)
         .doc("Terminate server application");
@@ -110,6 +112,8 @@ int main(int, char **)
         .add("extra", test.dir)
         .doc("Example of an instance directory");
 
+    senf::console::root().link("ex", test.dir);
+
     senf::console::Server::start( senf::INet4SocketAddress(23232u) )
         .name("testServer");
 
diff --git a/Utils/ScopeExit.cci b/Utils/ScopeExit.cci
new file mode 100644
index 000000000..09ff9cfee
--- /dev/null
+++ b/Utils/ScopeExit.cci
@@ -0,0 +1,54 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// 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 ScopeExit inline non-template implementation */
+
+//#include "ScopeExit.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::ScopeExit::ScopeExit(Function const & fn)
+    : fn_ (fn)
+{}
+
+prefix_ senf::ScopeExit::~ScopeExit()
+{
+    fn_();
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+
+// 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/Utils/ScopeExit.hh b/Utils/ScopeExit.hh
new file mode 100644
index 000000000..ee7262280
--- /dev/null
+++ b/Utils/ScopeExit.hh
@@ -0,0 +1,67 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// 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 ScopeExit public header */
+
+#ifndef HH_SENF_Utils_ScopeExit_
+#define HH_SENF_Utils_ScopeExit_ 1
+
+// Custom includes
+#include <boost/function.hpp>
+#include <boost/utility.hpp>
+
+//#include "ScopeExit.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+
+    class ScopeExit : boost::noncopyable
+    {
+    public:
+        typedef boost::function<void ()> Function;
+
+        explicit ScopeExit(Function const & fn);
+        ~ScopeExit();
+
+    private:
+        Function fn_;
+    };
+
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "ScopeExit.cci"
+//#include "ScopeExit.ct"
+//#include "ScopeExit.cti"
+#endif
+
+
+// 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/Utils/Termlib/Editor.cc b/Utils/Termlib/Editor.cc
index 9fc6e68e4..f3a0c1971 100644
--- a/Utils/Termlib/Editor.cc
+++ b/Utils/Termlib/Editor.cc
@@ -276,7 +276,7 @@ prefix_ void senf::term::BaseEditor::write(std::string const & s)
 ///////////////////////////////////////////////////////////////////////////
 
 prefix_ senf::term::LineEditor::LineEditor(AbstractTerminal & terminal, AcceptCallback cb)
-    : BaseEditor(terminal), enabled_ (true), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u), 
+    : BaseEditor(terminal), enabled_ (false), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u), 
       text_ (""), point_ (0u), displayPos_ (0u), lastKey_ (0u), callback_ (cb), historyPoint_ (0u)
 {
     defineKey(KeyParser::Return,    &bindings::accept);
@@ -521,7 +521,7 @@ prefix_ bool senf::term::LineEditor::cb_init()
     if (!BaseEditor::cb_init())
         return false;
     prompt(prompt_);
-    forceRedisplay();
+    show();
     return true;
 }
 
-- 
GitLab