Utils/Console: Parser based character classifiers
g0dil [Tue, 10 Feb 2009 15:12:10 +0000 (15:12 +0000)]
Utils/Logger: Quote filename for console directory in FileTarget
Utils/Logger: Add directory node return value to syslog-target and udp-target console commands

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1114 270642c3-0616-0410-b53a-bc976706d245

Utils/Console/Executor.hh
Utils/Console/Parse.cc
Utils/Console/Parse.hh
Utils/Console/Parse.ih
Utils/Logger/FileTarget.cc
Utils/Logger/SyslogTarget.cc
Utils/Logger/SyslogTarget.hh
Utils/Logger/SyslogUDPTarget.cc
Utils/Logger/SyslogUDPTarget.hh

index 540472d..6a950f0 100644 (file)
@@ -108,16 +108,17 @@ namespace console {
                                         /**< if autocomplete is enabled, path components which can
                                              be uniquely completed will be completed
                                              automatically. Disabled by default (but enabled
-                                             automatically by the interactive console) void
-                                             autocomplete(bool v). */
+                                             automatically by the interactive console). */
 
         Executor & autocomplete(bool v); ///< Set autocomplete status
                                         /**< \see autocomplete() */
 
+
         DirectoryNode & chroot() const; ///< Get root node
                                         /**< The root node defaults to senf::console::root(). If
                                              changed, all path references are relative to this node
                                              and objects outside that tree cannot be accessed. */ 
+
         Executor & chroot(DirectoryNode & node); ///< chroot into given directory
                                         /**< After this call, all path's are interpreted relative to
                                              \a node and only nodes in the tree rooted at \a node
index dece5df..65dcaf3 100644 (file)
@@ -393,7 +393,35 @@ senf::console::CommandParser::parseIncremental(std::string const & commands, Cal
                           parseLoop(commands.begin(), commands.end(), "<unknown>", cb) );
 }
 
-///////////////////////////////cc.e////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// Character sets
+
+prefix_ bool senf::console::CommandParser::isSpecialChar(char ch)
+{
+    return Impl::Grammar::special_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isPunctuationChar(char ch)
+{
+    return Impl::Grammar::punctuation_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isSpaceChar(char ch)
+{
+    return Impl::Grammar::space_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isInvalidChar(char ch)
+{
+    return Impl::Grammar::invalid_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isWordChar(char ch)
+{
+    return Impl::Grammar::word_p.test(ch);
+}
+
+/////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Parse.mpp"
 
index 5e8b0ac..7afbaa1 100644 (file)
@@ -615,6 +615,12 @@ namespace console {
                                                  to be terminated explicitly. This means, that the
                                                  last ';' is \e not optional in this case. */
 
+        static bool isSpecialChar(char ch); ///< Check, if \a ch is a special character
+        static bool isPunctuationChar(char ch); ///< Check, if \a ch is a punctuation character
+        static bool isSpaceChar(char ch); ///< Check, if \a ch is a space character
+        static bool isInvalidChar(char ch); ///< Check, if \a ch is an invalid character
+        static bool isWordChar(char ch); ///< Check, if \a ch is a word character
+
         /** \brief Exception thrown when the parser detects an error */
         struct ParserErrorException : public SyntaxErrorException
         { explicit ParserErrorException(std::string const & msg) : SyntaxErrorException(msg) {} };
index 38b9fc9..4f0569f 100644 (file)
@@ -78,6 +78,16 @@ namespace detail {
 
         ParseDispatcher & dispatcher;
 
+        //////////////////////////////////////////////////////////////////////////
+        // charachter sets
+        
+        static boost::spirit::chset<> special_p;
+        static boost::spirit::chset<> punctuation_p;
+        static boost::spirit::chset<> space_p;
+        static boost::spirit::chset<> invalid_p;
+        static boost::spirit::chset<> word_p;
+        static boost::spirit::distinct_parser<> keyword_p;
+
         ///////////////////////////////////////////////////////////////////////////
         // Errors
 
@@ -104,33 +114,8 @@ namespace detail {
                 punctuation, hexbyte, balanced_tokens, simple_argument, complex_argument, builtin, 
                 skip, statement, relpath, abspath, arguments, group_start, group_close, 
                 statement_end, opt_path;
-            boost::spirit::chset<> special_p, punctuation_p, space_p, invalid_p, word_p;
-            boost::spirit::distinct_parser<> keyword_p;
-
-            definition(CommandGrammar const & self) : 
-
-                // Characters with a special meaning within the parser
-                special_p ("/(){};\""),
-
-                // Additional characters which are returned as punctuation tokens
-                // (only allowed within '()').
-                punctuation_p (",="),
-
-                // Whitespace characters
-                space_p (" \t\n\r"),
-
-                // Invalid characters: All chars below \x20 (space) which are not space_p
-                // (don't put a \0 in the chset<> argument *string* ...)
-                invalid_p ( (boost::spirit::chset<>('\0') 
-                             | boost::spirit::chset<>("\x01-\x20")) - space_p ),
-
-                // Valid word characters
-                word_p (
-                    boost::spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p),
-
-                // Keywords must not be followed by a word char or '/'
-                keyword_p ( word_p | boost::spirit::ch_p('/') )
 
+            definition(CommandGrammar const & self)
             {
                 using namespace boost::spirit;
                 using namespace ::phoenix;
@@ -203,14 +188,14 @@ namespace detail {
                     ;
 
                 builtin
-                    =    keyword_p("cd") 
+                    =    self.keyword_p("cd") 
                       >> path_expected(path)
                       >> eps_p                    [ bind(&PD::builtin_cd)(d_, path_) ]
-                    |    keyword_p("ls")
+                    |    self.keyword_p("ls")
                       >> ! path
                       >> eps_p                    [ bind(&PD::builtin_ls)(d_, path_) ]
-                    |    keyword_p("exit")        [ bind(&PD::builtin_exit)(d_) ]
-                    |    keyword_p("help")
+                    |    self.keyword_p("exit")   [ bind(&PD::builtin_exit)(d_) ]
+                    |    self.keyword_p("help")
                       >> ! path
                       >> eps_p                    [ bind(&PD::builtin_help)(d_, path_) ]
                     ;
@@ -316,7 +301,7 @@ namespace detail {
                     |    ch_p(';')                [ token_ = construct_<Token>(
                                                         Token::CommandTerminator,
                                                         ";") ]
-                    |    punctuation_p            [ token_ = construct_<Token>(
+                    |    self.punctuation_p       [ token_ = construct_<Token>(
                                                         Token::OtherPunctuation,
                                                         construct_<std::string>(1u, arg1)) ]
                     ;
@@ -324,7 +309,7 @@ namespace detail {
                 word                    // Returns value in context.token
                     =    lexeme_d
                          [
-                             (+ word_p)           [ str_ = construct_<std::string>(arg1, arg2) ]
+                             (+ self.word_p)      [ str_ = construct_<std::string>(arg1, arg2) ]
                          ]
                       >> eps_p                    [ token_ = construct_<Token>(
                                                         Token::Word, 
@@ -347,7 +332,7 @@ namespace detail {
                     ;
 
                 skip
-                    =    space_p | comment_p('#')
+                    =    self.space_p | comment_p('#')
                     ;
 
                 ///////////////////////////////////////////////////////////////////
@@ -381,6 +366,19 @@ namespace detail {
         };
     };
 
+    template <class PD> boost::spirit::chset<> CommandGrammar<PD>::special_p (
+        "/(){};\"");
+    template <class PD> boost::spirit::chset<> CommandGrammar<PD>::punctuation_p (
+        ",=");
+    template <class PD> boost::spirit::chset<> CommandGrammar<PD>::space_p (
+        " \t\n\r");
+    template <class PD> boost::spirit::chset<> CommandGrammar<PD>::invalid_p ( 
+        (boost::spirit::chset<>('\0') | boost::spirit::chset<>("\x01-\x20")) - space_p );
+    template <class PD> boost::spirit::chset<> CommandGrammar<PD>::word_p (
+        boost::spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p);
+    template <class PD> boost::spirit::distinct_parser<> CommandGrammar<PD>::keyword_p (
+        word_p | boost::spirit::ch_p('/'));
+
 #endif
 
 }}}
index 52ebaf8..e15b3e8 100644 (file)
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
+namespace {
+    
+    std::string quoteFilename(std::string filename)
+    {
+        for (std::string::iterator i (filename.begin()); i != filename.end(); ++i)
+            if (! senf::console::CommandParser::isWordChar(*i))
+                *i = '_';
+        return filename;
+    }
+
+}
+
 prefix_ senf::log::FileTarget::FileTarget(std::string const & file)
-    : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(file, ofstream_t::member), 
+    : ofstream_t(file.c_str(), std::ofstream::app), 
+      IOStreamTarget(quoteFilename(file), ofstream_t::member), 
       file_(file)
 {
     consoleDir().add( "reopen", senf::membind(
index 7c85321..40cdd58 100644 (file)
@@ -68,10 +68,13 @@ prefix_ senf::log::SyslogTarget::RegisterConsole::RegisterConsole()
         .doc("Create new syslog target.");
 }
 
-prefix_ void senf::log::SyslogTarget::RegisterConsole::create(LogFacility facility)
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
+senf::log::SyslogTarget::RegisterConsole::create(LogFacility facility)
 {
-    detail::TargetRegistry::instance().dynamicTarget(
-        std::auto_ptr<Target>(new SyslogTarget(facility)));
+    std::auto_ptr<Target> tp (new SyslogTarget(facility));
+    Target & target (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return target.consoleDir().node().thisptr();
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index 0049f59..eeebbb9 100644 (file)
 
 // Custom includes
 #include <syslog.h>
+#include <boost/shared_ptr.hpp>
 #include "Target.hh"
 
 //#include "SyslogTarget.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
+
+    namespace console { class DirectoryNode; }
+
 namespace log {
     
     /** \brief Log target writing to the syslog
@@ -118,7 +122,8 @@ namespace log {
     private:
         struct RegisterConsole {
             RegisterConsole();
-            static void create(LogFacility facility);
+            static boost::shared_ptr<senf::console::DirectoryNode> create(
+                LogFacility facility);
             static RegisterConsole instance;
         };
     };
index af8da40..e420ec5 100644 (file)
@@ -84,62 +84,74 @@ prefix_ senf::log::SyslogUDPTarget::RegisterConsole::RegisterConsole()
     namespace kw = senf::console::kw;
 
     detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", static_cast<void (*)(INet4SocketAddress const &, LogFacility)>(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &, LogFacility)>(
             &RegisterConsole::create))
         .arg("address", "target address to send log messages to")
         .arg("facility", "syslog facility to send messages to. One of\n"
-             "                  AUTHPRIV, CRON, DAEMON, FTP, KERN, LPR, MAIL, NEWS, SYSLOG, USER,\n"
-             "                  UUCP, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7",
+             "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
+             "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
              kw::default_value = USER)
         .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
              "number is omitted, it defaults to the default syslog port 514.");
     detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", static_cast<void (*)(INet4Address const &, LogFacility)>(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet4Address const &, LogFacility)>(
             &RegisterConsole::create))
         .arg("address")
         .arg("facility", kw::default_value = USER);
     detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", static_cast<void (*)(INet6SocketAddress const &, LogFacility)>(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &, LogFacility)>(
             &RegisterConsole::create))
         .arg("address")
         .arg("facility", kw::default_value = USER);
     detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", static_cast<void (*)(INet6Address const &, LogFacility)>(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet6Address const &, LogFacility)>(
             &RegisterConsole::create))
         .arg("address")
         .arg("facility", kw::default_value = USER);
 }
 
-prefix_ void
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4SocketAddress const & target,
                                                     LogFacility facility)
 {
-    detail::TargetRegistry::instance().dynamicTarget(
-        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
 }
 
-prefix_ void
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4Address const & target,
                                                     LogFacility facility)
 {
-    detail::TargetRegistry::instance().dynamicTarget(
-        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
 }
 
-prefix_ void
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6SocketAddress const & target,
                                                     LogFacility facility)
 {
-    detail::TargetRegistry::instance().dynamicTarget(
-        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
 }
 
-prefix_ void
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6Address const & target,
                                                     LogFacility facility)
 {
-    detail::TargetRegistry::instance().dynamicTarget(
-        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index e6f35ff..b940153 100644 (file)
@@ -154,14 +154,14 @@ namespace log {
 
         struct RegisterConsole {
             RegisterConsole();
-            static void create(senf::INet4SocketAddress const & target, 
-                               LogFacility facility = USER);
-            static void create(senf::INet4Address const & target,
-                               LogFacility facility = USER);
-            static void create(senf::INet6SocketAddress const & target,
-                               LogFacility facility = USER);
-            static void create(senf::INet6Address const & target,
-                               LogFacility facility = USER);
+            static boost::shared_ptr<senf::console::DirectoryNode> create(
+                senf::INet4SocketAddress const & target, LogFacility facility = USER);
+            static boost::shared_ptr<senf::console::DirectoryNode> create(
+                senf::INet4Address const & target, LogFacility facility = USER);
+            static boost::shared_ptr<senf::console::DirectoryNode> create(
+                senf::INet6SocketAddress const & target, LogFacility facility = USER);
+            static boost::shared_ptr<senf::console::DirectoryNode> create(
+                senf::INet6Address const & target, LogFacility facility = USER);
             static RegisterConsole instance;
         };
     };