From 30c616e65d370a8c4f5611bdb2cfa6f586b50f63 Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Sun, 23 Mar 2008 12:40:06 +0000
Subject: [PATCH] Console: Implement 'cd -' Console: Add
 CommandParser::parseFile implementation Console: Adourn 'ls' output with type
 information

---
 Console/Executor.cc  | 69 ++++++++++++++++++++++++++++----------------
 Console/Executor.cci |  2 +-
 Console/Executor.hh  |  1 +
 Console/Parse.cc     | 21 ++++++++++++--
 Console/Parse.hh     |  1 +
 Utils/Externals.dox  |  3 ++
 6 files changed, 68 insertions(+), 29 deletions(-)

diff --git a/Console/Executor.cc b/Console/Executor.cc
index 71c3f786a..43fc6d24c 100644
--- a/Console/Executor.cc
+++ b/Console/Executor.cc
@@ -56,8 +56,16 @@ prefix_ bool senf::console::Executor::operator()(ParseCommandInfo const & comman
 
     case ParseCommandInfo::BuiltinLS :
         for (DirectoryNode::child_iterator i (cwd().children().begin());
-             i != cwd().children().end(); ++i)
-            output << i->first << "\n";
+             i != cwd().children().end(); ++i) {
+            output << i->first;
+            try {
+                (void) cwd()(i->first);
+            }
+            catch (std::bad_cast &) {
+                output << "/";
+            }
+            output << "\n";
+        }
         break;
 
     case ParseCommandInfo::BuiltinPUSHD :
@@ -82,33 +90,44 @@ prefix_ bool senf::console::Executor::operator()(ParseCommandInfo const & comman
 
 prefix_ bool senf::console::Executor::chdir(ParseCommandInfo::argument_value_type const & path)
 {
-    try {
-        DirectoryNode::ptr dir (cwd_.lock());
-        ParseCommandInfo::token_iterator i (path.begin());
-        ParseCommandInfo::token_iterator const i_end (path.end());
-        if (i != i_end && i->value().empty()) {
-            dir = boost::static_pointer_cast<DirectoryNode>(
+    if (path.size() == 1 && path.begin()->value() == "-") {
+        if (oldCwd_.expired()) {
+            oldCwd_ = cwd_;
+            cwd_ = boost::static_pointer_cast<DirectoryNode>(
                 root().shared_from_this());
-            ++ i;
-        }
-        for (; i != i_end; ++i) {
-            if (i->value() == "..") {
-                dir = dir->parent(); 
-                if (! dir)
+        } else
+            swap(cwd_, oldCwd_);
+    }
+    else {
+        try {
+            DirectoryNode::ptr dir (cwd_.lock());
+            ParseCommandInfo::token_iterator i (path.begin());
+            ParseCommandInfo::token_iterator const i_end (path.end());
+            if (i != i_end && i->value().empty()) {
+                dir = boost::static_pointer_cast<DirectoryNode>(
+                    root().shared_from_this());
+                ++ i;
+            }
+            for (; i != i_end; ++i) {
+                if (i->value() == "..") {
+                    dir = dir->parent(); 
+                    if (! dir)
+                        dir = boost::static_pointer_cast<DirectoryNode>(
+                            root().shared_from_this());
+                }
+                else if (! i->value().empty() && i->value() != ".")
                     dir = boost::static_pointer_cast<DirectoryNode>(
-                        root().shared_from_this());
+                        (*dir)[i->value()].shared_from_this());
             }
-            else if (! i->value().empty() && i->value() != ".")
-                dir = boost::static_pointer_cast<DirectoryNode>(
-                    (*dir)[i->value()].shared_from_this());
+            oldCwd_ = cwd_;
+            cwd_ = dir;
+        }
+        catch (std::bad_cast &) {
+            return false;
+        }
+        catch (UnknownNodeNameException &) {
+            return false;
         }
-        cwd_ = dir;
-    }
-    catch (std::bad_cast &) {
-        return false;
-    }
-    catch (UnknownNodeNameException &) {
-        return false;
     }
     return true;
 }
diff --git a/Console/Executor.cci b/Console/Executor.cci
index 6c20c2f53..3126fa175 100644
--- a/Console/Executor.cci
+++ b/Console/Executor.cci
@@ -35,7 +35,7 @@
 
 prefix_ senf::console::Executor::Executor()
 {
-    cwd_ = boost::static_pointer_cast<DirectoryNode>(
+    oldCwd_ = cwd_ = boost::static_pointer_cast<DirectoryNode>(
         root().shared_from_this());
 }
 
diff --git a/Console/Executor.hh b/Console/Executor.hh
index be6f15f16..bc3ce99f2 100644
--- a/Console/Executor.hh
+++ b/Console/Executor.hh
@@ -71,6 +71,7 @@ namespace console {
         bool chdir(ParseCommandInfo::argument_value_type const & path);
 
         DirectoryNode::weak_ptr cwd_;
+        DirectoryNode::weak_ptr oldCwd_;
         typedef std::vector<DirectoryNode::weak_ptr> DirStack;
         DirStack dirstack_;
     };
diff --git a/Console/Parse.cc b/Console/Parse.cc
index f143149c6..a631f0f1c 100644
--- a/Console/Parse.cc
+++ b/Console/Parse.cc
@@ -27,8 +27,11 @@
 #include "Parse.ih"
 
 // Custom includes
-#include "../Utils/String.hh"
+#include <cerrno>
 #include <boost/iterator/transform_iterator.hpp>
+#include <boost/spirit/iterator/file_iterator.hpp>
+#include "../Utils/String.hh"
+#include "../Utils/Exception.hh"
 
 //#include "Parse.mpp"
 #define prefix_
@@ -223,8 +226,20 @@ prefix_ senf::console::CommandParser::~CommandParser()
 prefix_ bool senf::console::CommandParser::parse(std::string command, Callback cb)
 {
     detail::ParseDispatcher::BindInfo bind (impl().dispatcher, cb);
-#   warning don't use c_str() in parse and add istream parser. Implement error checking in parser.
-    return boost::spirit::parse( command.c_str(), 
+    return boost::spirit::parse( command.begin(), command.end(), 
+                                 impl().grammar.use_parser<Impl::Grammar::CommandParser>(),
+                                 impl().grammar.use_parser<Impl::Grammar::SkipParser>()
+        ).full;
+}
+
+prefix_ bool senf::console::CommandParser::parseFile(std::string filename, Callback cb)
+{
+    detail::ParseDispatcher::BindInfo bind (impl().dispatcher, 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());
+    
+    return boost::spirit::parse( i, i_end, 
                                  impl().grammar.use_parser<Impl::Grammar::CommandParser>(),
                                  impl().grammar.use_parser<Impl::Grammar::SkipParser>()
         ).full;
diff --git a/Console/Parse.hh b/Console/Parse.hh
index 9d22ede7c..a4e452c57 100644
--- a/Console/Parse.hh
+++ b/Console/Parse.hh
@@ -146,6 +146,7 @@ namespace console {
         ///////////////////////////////////////////////////////////////////////////
 
         bool parse(std::string command, Callback cb);
+        bool parseFile(std::string filename, Callback cb);
 
     private:
         struct Impl;
diff --git a/Utils/Externals.dox b/Utils/Externals.dox
index f517454db..9d1dc8ada 100644
--- a/Utils/Externals.dox
+++ b/Utils/Externals.dox
@@ -11,6 +11,9 @@ namespace boost { class noncopyable {}; }
 namespace boost { class singleton_pool {}; }
 namespace boost { class totally_ordered {}; }
 namespace boost { class true_type {}; }
+namespace boost { class enable_shared_from_this {}; }
+namespace boost { namespace spirit { class grammar {}; } }
+namespace boost { namespace spirit { class grammar_def {}; } }
 namespace std { class exception {}; }
 namespace std { class string {}; }
 ///\}
-- 
GitLab