GenericNode & node ( traverseCommand(command.commandPath()) );
DirectoryNode * dir ( dynamic_cast<DirectoryNode*>(&node) );
if ( dir ) {
- if (autocd_ && command.arguments().empty()) {
+ if (autocd_ && command.tokens().empty()) {
oldCwd_ = cwd_;
cwd_ = dir->thisptr();
} else
}
else {
oldCwd_ = cwd_;
- cwd_ = traverseDirectory(command.arguments().begin()[0]).thisptr();
+ cwd_ = traverseDirectory(*command.arguments().begin()).thisptr();
}
}
break;
case ParseCommandInfo::BuiltinLS : {
DirectoryNode const & dir ( command.arguments()
- ? traverseDirectory(command.arguments().begin()[0])
+ ? traverseDirectory(*command.arguments().begin())
: cwd() );
for (DirectoryNode::child_iterator i (dir.children().begin());
i != dir.children().end(); ++i) {
case ParseCommandInfo::BuiltinPUSHD :
dirstack_.push_back(cwd_);
if ( command.arguments() )
- cwd_ = traverseDirectory(command.arguments().begin()[0]).thisptr();
+ cwd_ = traverseDirectory(*command.arguments().begin()).thisptr();
break;
case ParseCommandInfo::BuiltinPOPD :
case ParseCommandInfo::BuiltinHELP :
GenericNode const & node (command.arguments()
- ? traverseNode(command.arguments().begin()[0])
+ ? traverseNode(*command.arguments().begin())
: cwd());
output << prettyName(typeid(node)) << " at " << node.path() << "\n\n";
node.help(output);
}
prefix_ senf::console::GenericNode &
-senf::console::Executor::traverseNode(ParseCommandInfo::argument_value_type const & path)
+senf::console::Executor::traverseNode(ParseCommandInfo::TokensRange const & path)
{
try {
return cwd().traverse(
}
prefix_ senf::console::DirectoryNode &
-senf::console::Executor::traverseDirectory(ParseCommandInfo::argument_value_type const & path)
+senf::console::Executor::traverseDirectory(ParseCommandInfo::TokensRange const & path)
{
try {
return dynamic_cast<DirectoryNode&>( traverseNode(path) );
protected:
private:
- GenericNode & traverseNode(ParseCommandInfo::argument_value_type const & path);
+ GenericNode & traverseNode(ParseCommandInfo::TokensRange const & path);
GenericNode & traverseCommand(ParseCommandInfo::CommandPathRange const & path);
- DirectoryNode & traverseDirectory(ParseCommandInfo::argument_value_type const & path);
+ DirectoryNode & traverseDirectory(ParseCommandInfo::TokensRange const & path);
struct InvalidPathException {};
struct InvalidDirectoryException {};
\code
void fun1(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
- // We take exactly one argument
- if (command.arguments().size() != 1)
+ ParseCommandInfo::ArgumentsRange args (command.arguments());
+ ParseCommandInfo::ArgumentsRange::iterator arg (args.begin());
+
+ // Check that we are not missing our argument
+ if (arg == args.end())
raise senf::console::SyntaxErrorException("invalid number of arguments");
- senf::console::ParseCommandInfo::TokensRange & argTokens (
- command.arguments()[0]);
+ senf::console::ParseCommandInfo::TokensRange & arg1Tokens ( *(arg++) );
+
+ // Check that we don't have additional arguments
+ if (arg != args.end())
+ raise senf::console::SyntaxErrorException("invalid number of arguments");
// The argument must have exactly one token
- if (argTokens.size() != 1)
+ if (arg1Tokens.size() != 1)
raise senf::console::SyntaxErrorException("argument syntax error");
// Retrieve the token value
static void setCommand(ParseCommandInfo & info, std::vector<std::string> & commandPath)
{ info.setCommand(commandPath); }
- static void startArgument(ParseCommandInfo & info)
- { info.startArgument(); }
-
- static void endArgument(ParseCommandInfo & info)
- { info.endArgument(); }
-
static void addToken(ParseCommandInfo & info, ArgumentToken const & token)
{ info.addToken(token); }
- static void finalize(ParseCommandInfo & info)
- { info.finalize(); }
-
- static ArgumentToken makeToken(std::string const & token)
- { return ArgumentToken(token); }
+ static ArgumentToken makeToken(ArgumentToken::TokenType type, std::string const & token)
+ { return ArgumentToken(type, token); }
};
struct ParseDispatcher
ParserAccess::setCommand(info_, command); }
void endCommand()
- { ParserAccess::finalize(info_); cb_(info_); }
+ { cb_(info_); }
- void pushArgument(std::string const & argument)
- { ParserAccess::startArgument(info_);
- ParserAccess::addToken(info_, ParserAccess::makeToken(argument));
- ParserAccess::endArgument(info_); }
+ void pushArgument(ArgumentToken::TokenType type, std::string const & argument)
+ { ParserAccess::addToken(info_, ParserAccess::makeToken(type, argument)); }
void openGroup()
- { ParserAccess::startArgument(info_); }
+ { pushPunctuation("("); }
void closeGroup()
- { ParserAccess::endArgument(info_); }
+ { pushPunctuation(")"); }
void pushPunctuation(std::string const & token)
- { ParserAccess::addToken(info_, ParserAccess::makeToken(token)); }
+ {
+ ArgumentToken::TokenType type;
+ switch (token[0]) {
+ case '/' : type = ArgumentToken::PathSeparator; break;
+ case '(' : type = ArgumentToken::ArgumentGroupOpen; break;
+ case ')' : type = ArgumentToken::ArgumentGroupClose; break;
+ case '{' : type = ArgumentToken::DirectoryGroupOpen; break;
+ case '}' : type = ArgumentToken::DirectoryGroupClose; break;
+ case ';' : type = ArgumentToken::CommandTerminator; break;
+ default : type = ArgumentToken::OtherPunctuation; break;
+ }
+ ParserAccess::addToken(info_, ParserAccess::makeToken(type, token));
+ }
- void pushWord(std::string const & token)
- { ParserAccess::addToken(info_, ParserAccess::makeToken(token)); }
+ void pushWord(ArgumentToken::TokenType type, std::string const & token)
+ { ParserAccess::addToken(info_, ParserAccess::makeToken(type, token)); }
void builtin_cd(std::vector<std::string> & path)
{ ParserAccess::init(info_);
ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinCD);
setBuiltinPathArg(path);
- ParserAccess::finalize(info_); cb_(info_); }
+ cb_(info_); }
void builtin_ls(std::vector<std::string> & path)
{ ParserAccess::init(info_);
ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinLS);
setBuiltinPathArg(path);
- ParserAccess::finalize(info_); cb_(info_); }
+ cb_(info_); }
void pushDirectory(std::vector<std::string> & path)
{ ParserAccess::init(info_);
ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinPUSHD);
setBuiltinPathArg(path);
- ParserAccess::finalize(info_); cb_(info_); }
+ cb_(info_); }
void popDirectory()
{ ParserAccess::init(info_);
ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinPOPD);
- ParserAccess::finalize(info_); cb_(info_); }
+ cb_(info_); }
void builtin_exit()
{ ParserAccess::init(info_);
ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinEXIT);
- ParserAccess::finalize(info_); cb_(info_); }
+ cb_(info_); }
void builtin_help(std::vector<std::string> & path)
{ ParserAccess::init(info_);
ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinHELP);
setBuiltinPathArg(path);
- ParserAccess::finalize(info_); cb_(info_); }
+ cb_(info_); }
void setBuiltinPathArg(std::vector<std::string> & path)
{
- ParserAccess::startArgument(info_);
+ pushPunctuation("(");
for (std::vector<std::string>::const_iterator i (path.begin());
i != path.end(); ++i)
- ParserAccess::addToken(info_, ParserAccess::makeToken(*i));
- ParserAccess::endArgument(info_);
+ ParserAccess::addToken(info_,
+ ParserAccess::makeToken(ArgumentToken::Word, *i));
+ pushPunctuation(")");
}
};
///////////////////////////////////////////////////////////////////////////
// senf::console::ParseCommandInfo
-#ifndef DOXYGEN
-
-struct senf::console::ParseCommandInfo::MakeRange
-{
- typedef ParseCommandInfo::argument_value_type result_type;
-
- MakeRange() {}
- MakeRange(ParseCommandInfo::token_iterator b) : b_ (b) {}
-
- senf::console::ParseCommandInfo::token_iterator b_;
-
- result_type operator()(TempArguments::iterator::value_type const & v) const {
- return result_type( b_ + v.first, b_ + v.second );
- }
-};
-
-#endif
-
-prefix_ void senf::console::ParseCommandInfo::finalize()
-{
- arguments_.resize( tempArguments_.size() );
-
- std::copy( boost::make_transform_iterator( tempArguments_.begin(),
- MakeRange(tokens_.begin()) ),
- boost::make_transform_iterator( tempArguments_.end(),
- MakeRange() ),
- arguments_.begin() );
-
- tempArguments_.clear();
-}
-
prefix_ std::ostream & senf::console::operator<<(std::ostream & stream,
ParseCommandInfo const & info)
{
}
///////////////////////////////////////////////////////////////////////////
+// senf::console::ParseCommandInfo::ArgumentIterator
+
+prefix_ void senf::console::ParseCommandInfo::ArgumentIterator::setRange()
+ const
+{
+ if (b_->is(ArgumentToken::ArgumentGroupOpen)) {
+ unsigned level (0);
+ e_ = b_;
+ for (;;) {
+ if (e_->is(ArgumentToken::ArgumentGroupOpen))
+ ++ level;
+ else if (e_->is(ArgumentToken::ArgumentGroupClose)) {
+ -- level;
+ if (level == 0)
+ break;
+ }
+ ++e_;
+ }
+ }
+ ++ e_;
+}
+
+prefix_ void senf::console::ParseCommandInfo::ArgumentIterator::decrement()
+{
+ e_ = b_;
+ --b_;
+ if (b_->is(ArgumentToken::ArgumentGroupClose)) {
+ unsigned level (0);
+ for (;;) {
+ if (b_->is(ArgumentToken::ArgumentGroupClose))
+ ++ level;
+ else if (b_->is(ArgumentToken::ArgumentGroupOpen)) {
+ -- level;
+ if (level == 0)
+ break;
+ }
+ --b_;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
// senf::console::CommandParser
#ifndef DOXYGEN
return token_;
}
-prefix_ senf::console::ArgumentToken::ArgumentToken(std::string token)
- : token_ (token)
+prefix_ senf::console::ArgumentToken::TokenType senf::console::ArgumentToken::type()
+ const
+{
+ return type_;
+}
+
+prefix_ bool senf::console::ArgumentToken::is(unsigned tokens)
+ const
+{
+ return tokens & type_;
+}
+
+prefix_ senf::console::ArgumentToken::ArgumentToken(TokenType type, std::string token)
+ : type_(type), token_ (token)
{}
///////////////////////////////////////////////////////////////////////////
senf::console::ParseCommandInfo::arguments()
const
{
- return boost::make_iterator_range(arguments_.begin(), arguments_.end());
+ return boost::make_iterator_range( ArgumentIterator(tokens_.begin()),
+ ArgumentIterator(tokens_.end()) );
}
prefix_ senf::console::ParseCommandInfo::TokensRange senf::console::ParseCommandInfo::tokens()
builtin_ = NoBuiltin;
commandPath_.clear();
tokens_.clear();
- arguments_.clear();
- tempArguments_.clear();
}
prefix_ void senf::console::ParseCommandInfo::setBuiltin(BuiltinCommand builtin)
commandPath_.swap(commandPath);
}
-prefix_ void senf::console::ParseCommandInfo::startArgument()
+prefix_ void senf::console::ParseCommandInfo::addToken(ArgumentToken const & token)
{
- tempArguments_.push_back( TempArgumentRange( tokens_.size(), tokens_.size() ) );
+ tokens_.push_back(token);
}
-prefix_ void senf::console::ParseCommandInfo::endArgument()
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ParseCommandInfo::ArgumentIterator
+
+prefix_ senf::console::ParseCommandInfo::ArgumentIterator::ArgumentIterator()
+{}
+
+prefix_ senf::console::ParseCommandInfo::ArgumentIterator::
+ArgumentIterator(ParseCommandInfo::TokensRange::iterator i)
+ : b_(i), e_(i)
+{}
+
+prefix_ senf::console::ParseCommandInfo::ArgumentIterator::reference
+senf::console::ParseCommandInfo::ArgumentIterator::dereference()
+ const
{
- tempArguments_.back().second = tokens_.size();
+ if (b_ == e_) setRange();
+ return b_->is(ArgumentToken::ArgumentGroupOpen)
+ ? boost::make_iterator_range(boost::next(b_), boost::prior(e_))
+ : boost::make_iterator_range(b_, e_);
}
-prefix_ void senf::console::ParseCommandInfo::addToken(ArgumentToken const & token)
+prefix_ bool
+senf::console::ParseCommandInfo::ArgumentIterator::equal(ArgumentIterator const & other)
+ const
{
- tokens_.push_back(token);
+ return b_ == other.b_;
+}
+
+prefix_ void senf::console::ParseCommandInfo::ArgumentIterator::increment()
+{
+ if (b_ == e_) setRange();
+ b_ = e_;
}
///////////////////////////////////////////////////////////////////////////
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/range/iterator_range.hpp>
+#include <boost/iterator/iterator_facade.hpp>
#include <boost/function.hpp>
//#include "Parse.mpp"
class ArgumentToken
{
public:
+ enum TokenType {
+ PathSeparator = 0x0001,
+ ArgumentGroupOpen = 0x0002,
+ ArgumentGroupClose = 0x0004,
+ DirectoryGroupOpen = 0x0008,
+ DirectoryGroupClose = 0x0010,
+ CommandTerminator = 0x0020,
+ OtherPunctuation = 0x0040,
+ BasicString = 0x0080,
+ HexString = 0x0100,
+ Word = 0x0200
+ };
+
+ enum TokenGroup {
+ ArgumentGrouper = ArgumentGroupOpen
+ | ArgumentGroupClose,
+
+ DirectoryGrouper = DirectoryGroupOpen
+ | DirectoryGroupClose,
+
+ Punctuation = DirectoryGroupOpen
+ | DirectoryGroupClose
+ | PathSeparator
+ | CommandTerminator
+ | OtherPunctuation,
+
+ String = BasicString
+ | HexString,
+
+ SimpleArgument = Word
+ | BasicString
+ | HexString
+ };
+
std::string const & value() const; ///< String value of token
/**< This value is properly unquoted */
+ TokenType type() const; ///< Token type
+
+ bool is(unsigned tokens) const; ///< Check, whether tokens type matches \a tokens
+ /**< \a tokens is a bit-mask of token types to check. */
+
protected:
private:
- explicit ArgumentToken(std::string token);
+ ArgumentToken(TokenType type, std::string token);
+ TokenType type_;
std::string token_;
friend class detail::ParserAccess;
\li the arguments. Every argument consists of a range of ArgumentToken instances.
\ingroup console_parser
-
- \todo Completely change the 'arguments()' member implementation: let the parser just
- generate a flat list of tokens and implement an 'argument iterator' with the following
- features: 1. return argument ranges, automatically detecting paranthesis 2. trying to
- increment the iterator beyond it's range just throws an argument syntax error. For this
- to work, the parser needs to not drop the outermost '()' pair 3. detect bad paranthesis
- (should not be necessary since the parser already does this). This allows to use this
- same iterator to parse nested complex arguments.
*/
class ParseCommandInfo
{
typedef std::vector<ArgumentToken> Tokens;
typedef std::vector<std::string> CommandPath;
-
+ class ArgumentIterator;
+
public:
typedef CommandPath::const_iterator path_iterator;
typedef Tokens::const_iterator token_iterator;
- typedef boost::iterator_range<token_iterator> argument_value_type;
-
-
- private:
- typedef std::vector<argument_value_type> Arguments;
-
- public:
- typedef Arguments::const_iterator argument_iterator;
- typedef Arguments::size_type size_type;
+ typedef ArgumentIterator argument_iterator;
+ typedef Tokens::size_type size_type;
typedef boost::iterator_range<path_iterator> CommandPathRange;
typedef boost::iterator_range<argument_iterator> ArgumentsRange;
void init();
void setBuiltin(BuiltinCommand builtin);
void setCommand(std::vector<std::string> & commandPath);
- void startArgument();
- void endArgument();
void addToken(ArgumentToken const & token);
- void finalize();
struct MakeRange;
std::vector<std::string> commandPath_;
-
- typedef std::pair<Tokens::size_type, Tokens::size_type> TempArgumentRange;
- typedef std::vector<TempArgumentRange> TempArguments;
-
BuiltinCommand builtin_;
Tokens tokens_;
- Arguments arguments_;
- TempArguments tempArguments_;
friend class detail::ParserAccess;
};
+ class ParseCommandInfo::ArgumentIterator
+ : public boost::iterator_facade< ParseCommandInfo::ArgumentIterator,
+ ParseCommandInfo::TokensRange,
+ boost::bidirectional_traversal_tag,
+ ParseCommandInfo::TokensRange >
+ {
+ ArgumentIterator();
+
+ private:
+ ArgumentIterator(ParseCommandInfo::TokensRange::iterator i);
+
+ reference dereference() const;
+ bool equal(ArgumentIterator const & other) const;
+ void increment();
+ void decrement();
+
+ mutable ParseCommandInfo::TokensRange::iterator b_;
+ mutable ParseCommandInfo::TokensRange::iterator e_;
+
+ void setRange() const;
+
+ friend class boost::iterator_core_access;
+ friend class ParseCommandInfo;
+ };
+
/**< \brief Output ParseCommandInfo instance
\related ParseCommandInfo
*/
///////////////////////////////////////////////////////////////////////////
// The parse context (variables needed while parsing)
+ typedef ArgumentToken::TokenType TokenType;
+
struct Context {
std::string str;
std::vector<std::string> path;
char ch;
+ TokenType type;
+
+ // OUCH ... This is sooooo stupid .. push_back_a and assign_a take their
+ // arguments by const-reference and STORE the REFERENCE ... they do NOT accept
+ // literal values !!!!!!
+ static const TokenType BasicString;
+ static const TokenType HexString;
+ static const TokenType Word;
+ static const std::string EmptyString;
};
Context & context;
Dispatch_actor dispatch(Callback cb, Arg const & arg) const
{ return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg)); }
+ template <class Callback, class Arg1, class Arg2>
+ Dispatch_actor dispatch(Callback cb, Arg1 const & arg1, Arg2 const & arg2) const
+ { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg1, arg2)); }
+
///////////////////////////////////////////////////////////////////////////
CommandGrammar(ParseDispatcher & d, Context & c)
argument
= simple_argument [ self.dispatch(&PD::pushArgument,
+ boost::ref(self.context.type),
boost::ref(self.context.str)) ]
| complex_argument
;
string // Returns value in context.str
= eps_p [ clear_a(self.context.str) ]
+ >> eps_p [ assign_a(self.context.type,
+ self.context.BasicString) ]
>> lexeme_d
[
ch_p('"')
hexstring // Returns value in context.str
= eps_p [ clear_a(self.context.str) ]
+ >> eps_p [ assign_a(self.context.type,
+ self.context.HexString) ]
>> confix_p( "x\"", * hexbyte, '"' )
;
;
relpath
- = ( word [ push_back_a(self.context.path) ]
+ = ( word [ push_back_a(self.context.path) ]
% ch_p('/') )
- >> ( ! ch_p('/') [ push_back_a(self.context.path,"") ] )
+ >> ( ! ch_p('/') [ push_back_a(self.context.path,
+ self.context.EmptyString) ] )
;
abspath
- = ch_p('/') [ push_back_a(self.context.path, "") ]
+ = ch_p('/') [ push_back_a(self.context.path,
+ self.context.EmptyString) ]
>> ( relpath
| eps_p [ push_back_a(self.context.path, "") ] )
;
;
token
- = simple_argument [ self.dispatch(&PD::pushWord,
+ = simple_argument [ self.dispatch(&PD::pushWord,
+ boost::ref(self.context.type),
boost::ref(self.context.str)) ]
| punctuation [ self.dispatch(&PD::pushPunctuation,
boost::ref(self.context.str)) ]
;
word // Returns value in context.str
- = lexeme_d[ + word_p ] [ assign_a(self.context.str) ]
+ = lexeme_d
+ [
+ eps_p [ assign_a(self.context.type,
+ self.context.Word) ]
+ >> (+ word_p) [ assign_a(self.context.str) ]
+ ]
;
hexbyte
};
};
+ template <class ParseDispatcher>
+ ArgumentToken::TokenType const CommandGrammar<ParseDispatcher>::Context::BasicString (
+ ArgumentToken::BasicString);
+
+ template <class ParseDispatcher>
+ ArgumentToken::TokenType const CommandGrammar<ParseDispatcher>::Context::HexString(
+ ArgumentToken::HexString);
+ template <class ParseDispatcher>
+ ArgumentToken::TokenType const CommandGrammar<ParseDispatcher>::Context::Word(
+ ArgumentToken::Word);
+
+ template <class ParseDispatcher>
+ std::string const CommandGrammar<ParseDispatcher>::Context::EmptyString;
#endif
void endCommand()
{ os_ << "endCommand()\n"; }
- void pushArgument(std::string const & argument)
+ void pushArgument(senf::console::ArgumentToken::TokenType type,
+ std::string const & argument)
{ os_ << "pushArgument( " << argument << " )\n"; }
void openGroup()
{ os_ << "openGroup()\n"; }
{ os_ << "closeGroup()\n"; }
void pushPunctuation(std::string const & token)
{ os_ << "pushPunctuation( " << token << " )\n"; }
- void pushWord(std::string const & token)
+ void pushWord(senf::console::ArgumentToken::TokenType type,
+ std::string const & token)
{ os_ << "pushWord( " << token << " )\n"; }
void builtin_cd(std::vector<std::string> const & path)
BOOST_CHECK_EQUAL_COLLECTIONS( info.commandPath().begin(), info.commandPath().end(),
path, path + sizeof(path)/sizeof(path[0]) );
- BOOST_REQUIRE_EQUAL( info.arguments().size(), 6u );
- BOOST_REQUIRE_EQUAL( info.tokens().size(), 13u );
+ BOOST_CHECK_EQUAL( info.tokens().size(), 15u );
char const * tokens[] = { "arg",
"flab::blub",
"123.434>a",
- "a", ",", "b", ",", "c", "(", "huhu", ")",
+ "(", "a", ",", "b", ",", "c", "(", "huhu", ")", ")",
"foo\"bar",
"\x01\x02\x03\x04" };
- BOOST_REQUIRE_EQUAL( info.arguments().begin()[0].size(), 1u );
- BOOST_CHECK_EQUAL( info.arguments().begin()[0].begin()->value(), tokens[0] );
-
- BOOST_REQUIRE_EQUAL( info.arguments().begin()[1].size(), 1u );
- BOOST_CHECK_EQUAL( info.arguments().begin()[1].begin()->value(), tokens[1] );
-
- BOOST_REQUIRE_EQUAL( info.arguments().begin()[2].size(), 1u );
- BOOST_CHECK_EQUAL( info.arguments().begin()[2].begin()->value(), tokens[2] );
-
- BOOST_REQUIRE_EQUAL( info.arguments().begin()[3].size(), 8u );
+ senf::console::ParseCommandInfo::argument_iterator args (info.arguments().begin());
+ BOOST_REQUIRE( args != info.arguments().end() );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
+ BOOST_CHECK_EQUAL( args->begin()->value(), tokens[0] );
+
+ ++ args;
+ BOOST_REQUIRE( args != info.arguments().end() );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
+ BOOST_CHECK_EQUAL( args->begin()->value(), tokens[1] );
+
+ ++ args;
+ BOOST_REQUIRE( args != info.arguments().end() );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
+ BOOST_CHECK_EQUAL( args->begin()->value(), tokens[2] );
+
+ ++ args;
+ BOOST_REQUIRE( args != info.arguments().end() );
+ BOOST_REQUIRE_EQUAL( args->size(), 8u );
for (unsigned i (0); i<8; ++i)
- BOOST_CHECK_EQUAL( info.arguments().begin()[3].begin()[i].value(), tokens[3+i] );
+ BOOST_CHECK_EQUAL( args->begin()[i].value(), tokens[4+i] );
+
+ ++ args;
+ BOOST_REQUIRE( args != info.arguments().end() );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
+ BOOST_CHECK_EQUAL( args->begin()->value(), tokens[13] );
- BOOST_REQUIRE_EQUAL( info.arguments().begin()[4].size(), 1u );
- BOOST_CHECK_EQUAL( info.arguments().begin()[4].begin()->value(), tokens[11] );
+ ++ args;
+ BOOST_REQUIRE( args != info.arguments().end() );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
+ BOOST_CHECK_EQUAL( args->begin()->value(), tokens[14] );
- BOOST_REQUIRE_EQUAL( info.arguments().begin()[5].size(), 1u );
- BOOST_CHECK_EQUAL( info.arguments().begin()[5].begin()->value(), tokens[12] );
+ ++ args;
+ BOOST_CHECK( args == info.arguments().end() );
}
///////////////////////////////cc.e////////////////////////////////////////
v_execute(std::ostream & os, ParseCommandInfo const & command)
const
{
- if ( command.arguments().size() > BOOST_PP_ITERATION() )
+ // We NEED to know the number of arguments beforehand so we can assign default values
+ // correctly ... hrmpf ...
+ unsigned nArgs ( command.arguments().size() );
+ if ( nArgs > BOOST_PP_ITERATION() )
throw SyntaxErrorException("invalid number of arguments");
- int nDefaults ( BOOST_PP_ITERATION() - command.arguments().size() );
+ int nDefaults ( BOOST_PP_ITERATION() - nArgs );
typedef typename boost::range_const_reverse_iterator<ParseCommandInfo::ArgumentsRange>::type
riterator;
v_execute(std::ostream & os, ParseCommandInfo const & command)
const
{
- if ( command.arguments().size() > BOOST_PP_ITERATION() )
+ // We NEED to know the number of arguments beforehand so we can assign default values
+ // correctly ... hrmpf ...
+ unsigned nArgs ( command.arguments().size() );
+ if ( nArgs > BOOST_PP_ITERATION() )
throw SyntaxErrorException("invalid number of arguments");
- int nDefaults ( BOOST_PP_ITERATION() - command.arguments().size() );
+ int nDefaults ( BOOST_PP_ITERATION() - nArgs );
typedef typename boost::range_const_reverse_iterator<ParseCommandInfo::ArgumentsRange>::type
riterator;
void echo(std::ostream & output, senf::console::ParseCommandInfo const & command)
{
- typedef senf::console::ParseCommandInfo::ArgumentsRange::iterator iterator;
- iterator i (command.arguments().begin());
- iterator i_end (command.arguments().end());
+ typedef senf::console::ParseCommandInfo::TokensRange::iterator iterator;
+ iterator i (command.tokens().begin());
+ iterator i_end (command.tokens().end());
for (; i != i_end; ++i) {
- iterator::value_type::iterator j (i->begin());
- iterator::value_type::iterator j_end (i->end());
- for (; j != j_end; ++j)
- output << j->value() << ' ';
+ output << i->value() << ' ';
}
output << "\n";
}
#include <unistd.h>
#include <fcntl.h>
#include "../Utils/Exception.hh"
+#include "../Utils/Backtrace.hh"
static const int EPollInitialSize = 16;
eventTime_(0), eventEarly_(ClockService::milliseconds(11)), eventAdjust_(0)
{
if (epollFd_<0)
- SENF_THROW_SYSTEM_EXCEPTION("");
+ SENF_THROW_SYSTEM_EXCEPTION("::epoll_create()");
if (::pipe(sigpipe_) < 0)
- SENF_THROW_SYSTEM_EXCEPTION("");
+ SENF_THROW_SYSTEM_EXCEPTION("::pipe()");
int flags (::fcntl(sigpipe_[1],F_GETFL));
if (flags < 0)
- SENF_THROW_SYSTEM_EXCEPTION("");
+ SENF_THROW_SYSTEM_EXCEPTION("::fcntl(F_GETFL)");
flags |= O_NONBLOCK;
if (::fcntl(sigpipe_[1], F_SETFL, flags) < 0)
- SENF_THROW_SYSTEM_EXCEPTION("");
+ SENF_THROW_SYSTEM_EXCEPTION("::fcntl(F_SETFL)");
::epoll_event ev;
::memset(&ev, 0, sizeof(ev));
ev.events = EV_READ;
ev.data.fd = sigpipe_[0];
if (::epoll_ctl(epollFd_, EPOLL_CTL_ADD, sigpipe_[0], &ev) < 0)
- SENF_THROW_SYSTEM_EXCEPTION("");
+ SENF_THROW_SYSTEM_EXCEPTION("::epoll_ctl(EPOLL_CTL_ADD)");
}
prefix_ void senf::Scheduler::registerSignal(unsigned signal, SimpleCallback const & cb)
action = EPOLL_CTL_ADD;
i = fdTable_.insert(std::make_pair(fd, EventSpec())).first;
}
- if (i->second.epollMask() == 0) {
+ else if (i->second.epollMask() == 0) {
action = EPOLL_CTL_ADD;
fdErase_.erase( std::remove(fdErase_.begin(), fdErase_.end(), unsigned(fd)),
fdErase_.end() );
ev.events = i->second.epollMask();
ev.data.fd = fd;
- if (! i->second.file && epoll_ctl(epollFd_, action, fd, &ev) < 0) {
- if (errno == EPERM) {
- // Argh ... epoll does not support ordinary files :-( :-(
- i->second.file = true;
- ++ files_;
+ for (;;) {
+ if ( (!i->second.file) && (epoll_ctl(epollFd_, action, fd, &ev) < 0) ) {
+ switch (errno) {
+ case EPERM :
+ // Argh ... epoll does not support ordinary files :-( :-(
+ i->second.file = true;
+ ++ files_;
+ return;
+ case ENOENT :
+ action = EPOLL_CTL_ADD;
+ break;
+ default:
+ SENF_THROW_SYSTEM_EXCEPTION("::epoll_ctl()");
+ }
}
else
- SENF_THROW_SYSTEM_EXCEPTION("::epoll_ctl()");
+ return;
}
}
fdErase_.push_back(fd);
}
- if (! file && epoll_ctl(epollFd_, action, fd, &ev) < 0)
+ if (! file && epoll_ctl(epollFd_, action, fd, &ev) < 0 && errno != ENOENT)
SENF_THROW_SYSTEM_EXCEPTION("::epoll_ctl()");
if (file)
-- files_;
if (signal == SIGCHLD)
sa.sa_flags |= SA_NOCLDSTOP;
if (::sigaction(signal, &sa, 0) < 0)
- SENF_THROW_SYSTEM_EXCEPTION("");
+ SENF_THROW_SYSTEM_EXCEPTION("::sigaction()");
}
}
}
///\todo Handle more than one epoll_event per call
struct epoll_event ev;
- ::sigprocmask(SIG_UNBLOCK, &sigset_, 0);
- int events (epoll_wait(epollFd_, &ev, 1, timeout));
- ::sigprocmask(SIG_BLOCK, &sigset_, 0);
+ if (::sigprocmask(SIG_UNBLOCK, &sigset_, 0) < 0)
+ SENF_THROW_SYSTEM_EXCEPTION("::sigprocmask(SIG_UNBLOCK)");
+ int events (::epoll_wait(epollFd_, &ev, 1, timeout));
+ if (::sigprocmask(SIG_BLOCK, &sigset_, 0) < 0)
+ SENF_THROW_SYSTEM_EXCEPTION("::sigprocmask(SIG_BLOCK)");
if (events<0)
if (errno != EINTR)
- SENF_THROW_SYSTEM_EXCEPTION("");
+ SENF_THROW_SYSTEM_EXCEPTION("::epoll_wait()");
eventTime_ = ClockService::now();
#include <execinfo.h>
#include <cxxabi.h>
#include <boost/regex.hpp>
+#include "Buffer.hh"
//#include "Backtrace.mpp"
#define prefix_
free(symbols);
}
+prefix_ void senf::backtrace(std::ostream & os, unsigned numEntries)
+{
+ SENF_SCOPED_BUFFER( void*, entries, numEntries);
+ unsigned n ( ::backtrace(entries, numEntries) );
+ senf::formatBacktrace(os, entries, n);
+}
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
namespace senf {
void formatBacktrace(std::ostream & os, void ** backtrace, unsigned numEntries);
+ void backtrace(std::ostream & os, unsigned numEntries);
}
pid = ::fork();
if (pid < 0) throw senf::SystemException("::fork()");
if (pid == 0) {
- ::_exit(myMain(argc, argv));
+ try {
+ ::_exit(myMain(argc, argv));
+ } catch (std::exception & ex) {
+ std::cerr << "Unexpected exception: " << ex.what() << std::endl;
+ } catch (...) {
+ std::cerr << "Unexpected exception" << std::endl;
+ }
+ ::_exit(2);
}
int status;
if (::waitpid(pid, &status, 0) < 0) throw senf::SystemException("::waitpid()");