Skip to content
Snippets Groups Projects
Commit bcf519cf authored by g0dil's avatar g0dil
Browse files

Utils/Console: Parser based character classifiers

Utils/Logger: Quote filename for console directory in FileTarget
Utils/Logger: Add directory node return value to syslog-target and udp-target console commands
parent 2978af66
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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"
......
......@@ -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) {} };
......
......@@ -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
}}}
......
......@@ -33,8 +33,21 @@
#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(
......
......@@ -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////////////////////////////////////////
......
......@@ -28,12 +28,16 @@
// 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;
};
};
......
......@@ -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////////////////////////////////////////
......
......@@ -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;
};
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment