From 13aff1d7a8b84b1b489aa84694d0ce086dd1fb5a Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 30 Nov 2017 10:29:34 -0800 Subject: [PATCH] ircd::rfc1459: Move grammars out of includes. --- include/ircd/rfc1459_gen.h | 157 ----------------- include/ircd/rfc1459_parse.h | 222 ------------------------ ircd/fmt.cc | 4 +- ircd/rfc1459.cc | 324 ++++++++++++++++++++++++++++++++++- 4 files changed, 321 insertions(+), 386 deletions(-) delete mode 100644 include/ircd/rfc1459_gen.h delete mode 100644 include/ircd/rfc1459_parse.h diff --git a/include/ircd/rfc1459_gen.h b/include/ircd/rfc1459_gen.h deleted file mode 100644 index 695eeed18..000000000 --- a/include/ircd/rfc1459_gen.h +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Copyright (C) 2016 Charybdis Development Team - * Copyright (C) 2016 Jason Volk - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once -#define HAVE_IRCD_RFC1459_GEN_H - -#include -#include "rfc1459_parse.h" - -namespace ircd { -namespace rfc1459 { -namespace gen { - -namespace karma = boost::spirit::karma; -using karma::lit; -using karma::int_; -using karma::char_; -using karma::buffer; -using karma::repeat; - -template -struct grammar -:karma::grammar -{ - std::string trail_save; - - karma::rule space; - karma::rule colon; - karma::rule terminator; - - karma::rule hostname; - karma::rule user; - karma::rule nick; - karma::rule prefix; - karma::rule prefix_optionals; - - karma::rule trailing; - karma::rule middle; - karma::rule params; - - karma::rule command_numeric; - karma::rule command_alpha; - karma::rule command; - karma::rule line; - - grammar(karma::rule &top_rule); -}; - -template -rfc1459::gen::grammar::grammar(karma::rule &top_rule) -:grammar::base_type -{ - top_rule -} -,space // A single space character -{ - lit(' ') - ,"space" -} -,colon // A single colon character -{ - lit(':') - ,"colon" -} -,terminator // The message terminator -{ - lit('\r') << lit('\n') - ,"terminator" -} -,hostname // A valid hostname -{ - +char_(charset(character::HOST)) // TODO: https://tools.ietf.org/html/rfc952 - ,"hostname" -} -,user // A valid username -{ - +char_(charset(character::USER)) - ,"user" -} -,nick // A valid nickname, leading letter followed by any NICK chars -{ - buffer[char_(charset(character::ALPHA)) << *char_(charset(character::NICK))] - ,"nick" -} -,prefix -{ - colon << nick << lit('!') << user << lit('@') << hostname - ,"prefix" -} -,prefix_optionals -{ - colon << (nick | lit('*')) - << lit('!') << (user | lit('*')) - << lit('@') << (hostname | lit('*')) - ,"prefix_optionals" -} -,trailing -{ - colon << +(~char_("\r\n")) - ,"trailing" -} -,middle // Spaced parameters -{ - ~char_(":\x20\r\n") << *(~char_("\x20\r\n")) - ,"middle" -} -,params //TODO: this doesn't work yet, don't use -{ - *(middle % space) << buffer[-trailing] - ,"params" -} -,command_numeric // \d\d\d numeric -{ - repeat(3)[char_(charset(character::DIGIT))] - ,"command_numeric" -} -,command_alpha -{ - +char_(charset(character::ALPHA)) - ,"command_alpha" -} -,command -{ - command_alpha | command_numeric - ,"command" -} -,line -{ - prefix << command << space << params << terminator - ,"line" -} -{ -} - -} // namespace gen -} // namespace rfc1459 -} // namespace ircd diff --git a/include/ircd/rfc1459_parse.h b/include/ircd/rfc1459_parse.h deleted file mode 100644 index ad28732e0..000000000 --- a/include/ircd/rfc1459_parse.h +++ /dev/null @@ -1,222 +0,0 @@ -/** - * Copyright (C) 2016 Charybdis Development Team - * Copyright (C) 2016 Jason Volk - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once -#define HAVE_IRCD_RFC1459_PARSE_H - -#include - -BOOST_FUSION_ADAPT_STRUCT -( - ircd::rfc1459::pfx - ,( decltype(ircd::rfc1459::pfx::nick), nick ) - ,( decltype(ircd::rfc1459::pfx::user), user ) - ,( decltype(ircd::rfc1459::pfx::host), host ) -) - -BOOST_FUSION_ADAPT_STRUCT -( - ircd::rfc1459::line - ,( decltype(ircd::rfc1459::line::pfx), pfx ) - ,( decltype(ircd::rfc1459::line::cmd), cmd ) - ,( decltype(ircd::rfc1459::line::parv), parv ) -) - -namespace ircd { -namespace rfc1459 { -namespace parse { - -namespace qi = boost::spirit::qi; - -using qi::lit; -using qi::char_; -using qi::repeat; -using qi::attr; -using qi::eps; -using qi::raw; -using qi::omit; - -/* The grammar template class. - * This aggregates all the rules under one template to make composing them easier. - * - * The grammar template is instantiated by individual parsers depending on the goal - * for the specific parse, or the "top level." The first top-level was an IRC line, so - * a class was created `struct head` specifying grammar::line as the top rule, and - * rfc1459::line as the top output target to parse into. - */ -template -struct grammar -:qi::grammar -{ - qi::rule space; - qi::rule colon; - qi::rule nulcrlf; - qi::rule spnulcrlf; - qi::rule terminator; - - qi::rule hostname; - qi::rule server; - qi::rule user; - qi::rule nick; - qi::rule prefix; - - qi::rule trailing; - qi::rule middle; - qi::rule params; - - qi::rule numeric; - qi::rule command; - - qi::rule line; - qi::rule> tape; - - grammar(qi::rule &top_rule); -}; - -template -grammar::grammar(qi::rule &top_rule) -:grammar::base_type -{ - top_rule -} -,space // A single space character -{ - /* TODO: RFC says: - * 1) is consists only of SPACE character(s) (0x20). - * Specially notice that TABULATION, and all other control - * characters are considered NON-WHITE-SPACE. - * But our table in this namespace has control characters labeled as SPACE. - * This needs to be fixed. - */ - - //char_(charset(character::SPACE)) - lit(' ') - ,"space" -} -,colon // A single colon character -{ - lit(':') - ,"colon" -} -,nulcrlf // Match on NUL or CR or LF -{ - lit('\0') | lit('\r') | lit('\n') - ,"nulcrlf" -} -,spnulcrlf // Match on space or nulcrlf -{ - space | nulcrlf - ,"spnulcrlf" -} -,terminator // The message terminator -{ - lit('\r') >> lit('\n') - ,"terminator" -} -,hostname // A valid hostname -{ - raw[+char_(charset(character::HOST))] // TODO: https://tools.ietf.org/html/rfc952 - ,"hostname" -} -,server // A valid servername -{ - hostname - ,"server" -} -,user // A valid username -{ - raw[+char_(charset(character::USER))] - ,"user" -} -,nick // A valid nickname, leading letter followed by any NICK chars -{ - raw[char_(charset(character::ALPHA)) >> *char_(charset(character::NICK))] - ,"nick" -} -,prefix // A valid prefix, required name, optional user and host (or empty placeholders) -{ - colon >> (nick | server) >> -(lit('!') >> user) >> -(lit('@') >> hostname) - ,"prefix" -} -,trailing // Trailing string pinch -{ - colon >> raw[+(char_ - nulcrlf)] - ,"trailing" -} -,middle // Spaced parameters -{ - !colon >> raw[+(char_ - spnulcrlf)] - ,"middle" -} -,params // Parameter vector -{ - *(+space >> middle) >> -(+space >> trailing) - ,"params" -} -,numeric // \d\d\d numeric -{ - repeat(3)[char_(charset(character::DIGIT))] - ,"numeric" -} -,command // A command or numeric -{ - raw[+char_(charset(character::ALPHA)) | numeric] - ,"command" -} -,line -{ - -(prefix >> +space) >> command >> params - ,"line" -} -,tape -{ - +(-line >> +terminator) - ,"tape" -} -{ -} - -// Instantiate the input grammar to parse a const char* buffer into an rfc1459::line object. -// The top rule is inherited and then specified as grammar::line, which is compatible -// with an rfc1459::line object. -// -struct head -:parse::grammar -{ - head(): grammar{grammar::line} {} -} -extern const head; - -// Instantiate the input grammar to parse a const char* buffer into an rfc1459::tape object. -// The top rule is now grammar::tape and the target object is an rfc1459::tape deque. -// -struct capstan -:parse::grammar> -{ - capstan(): grammar{grammar::tape} {} -} -extern const capstan; - -} // namespace parse -} // namespace rfc1459 -} // namespace ircd diff --git a/ircd/fmt.cc b/ircd/fmt.cc index 72ef6b913..3509dc2e6 100644 --- a/ircd/fmt.cc +++ b/ircd/fmt.cc @@ -19,9 +19,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include BOOST_FUSION_ADAPT_STRUCT ( diff --git a/ircd/rfc1459.cc b/ircd/rfc1459.cc index d7acfc2bd..82591ecd2 100644 --- a/ircd/rfc1459.cc +++ b/ircd/rfc1459.cc @@ -21,23 +21,339 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#include namespace qi = boost::spirit::qi; namespace karma = boost::spirit::karma; +BOOST_FUSION_ADAPT_STRUCT +( + ircd::rfc1459::pfx + ,( decltype(ircd::rfc1459::pfx::nick), nick ) + ,( decltype(ircd::rfc1459::pfx::user), user ) + ,( decltype(ircd::rfc1459::pfx::host), host ) +) + +BOOST_FUSION_ADAPT_STRUCT +( + ircd::rfc1459::line + ,( decltype(ircd::rfc1459::line::pfx), pfx ) + ,( decltype(ircd::rfc1459::line::cmd), cmd ) + ,( decltype(ircd::rfc1459::line::parv), parv ) +) + namespace ircd { namespace rfc1459 { namespace parse { -decltype(head) head; -decltype(capstan) capstan; +namespace qi = boost::spirit::qi; + +using qi::lit; +using qi::char_; +using qi::repeat; +using qi::attr; +using qi::eps; +using qi::raw; +using qi::omit; + +/* The grammar template class. + * This aggregates all the rules under one template to make composing them easier. + * + * The grammar template is instantiated by individual parsers depending on the goal + * for the specific parse, or the "top level." The first top-level was an IRC line, so + * a class was created `struct head` specifying grammar::line as the top rule, and + * rfc1459::line as the top output target to parse into. + */ +template +struct grammar +:qi::grammar +{ + qi::rule space; + qi::rule colon; + qi::rule nulcrlf; + qi::rule spnulcrlf; + qi::rule terminator; + + qi::rule hostname; + qi::rule server; + qi::rule user; + qi::rule nick; + qi::rule prefix; + + qi::rule trailing; + qi::rule middle; + qi::rule params; + + qi::rule numeric; + qi::rule command; + + qi::rule line; + qi::rule> tape; + + grammar(qi::rule &top_rule); +}; + +template +grammar::grammar(qi::rule &top_rule) +:grammar::base_type +{ + top_rule +} +,space // A single space character +{ + /* TODO: RFC says: + * 1) is consists only of SPACE character(s) (0x20). + * Specially notice that TABULATION, and all other control + * characters are considered NON-WHITE-SPACE. + * But our table in this namespace has control characters labeled as SPACE. + * This needs to be fixed. + */ + + //char_(charset(character::SPACE)) + lit(' ') + ,"space" +} +,colon // A single colon character +{ + lit(':') + ,"colon" +} +,nulcrlf // Match on NUL or CR or LF +{ + lit('\0') | lit('\r') | lit('\n') + ,"nulcrlf" +} +,spnulcrlf // Match on space or nulcrlf +{ + space | nulcrlf + ,"spnulcrlf" +} +,terminator // The message terminator +{ + lit('\r') >> lit('\n') + ,"terminator" +} +,hostname // A valid hostname +{ + raw[+char_(charset(character::HOST))] // TODO: https://tools.ietf.org/html/rfc952 + ,"hostname" +} +,server // A valid servername +{ + hostname + ,"server" +} +,user // A valid username +{ + raw[+char_(charset(character::USER))] + ,"user" +} +,nick // A valid nickname, leading letter followed by any NICK chars +{ + raw[char_(charset(character::ALPHA)) >> *char_(charset(character::NICK))] + ,"nick" +} +,prefix // A valid prefix, required name, optional user and host (or empty placeholders) +{ + colon >> (nick | server) >> -(lit('!') >> user) >> -(lit('@') >> hostname) + ,"prefix" +} +,trailing // Trailing string pinch +{ + colon >> raw[+(char_ - nulcrlf)] + ,"trailing" +} +,middle // Spaced parameters +{ + !colon >> raw[+(char_ - spnulcrlf)] + ,"middle" +} +,params // Parameter vector +{ + *(+space >> middle) >> -(+space >> trailing) + ,"params" +} +,numeric // \d\d\d numeric +{ + repeat(3)[char_(charset(character::DIGIT))] + ,"numeric" +} +,command // A command or numeric +{ + raw[+char_(charset(character::ALPHA)) | numeric] + ,"command" +} +,line +{ + -(prefix >> +space) >> command >> params + ,"line" +} +,tape +{ + +(-line >> +terminator) + ,"tape" +} +{ +} + +// Instantiate the input grammar to parse a const char* buffer into an rfc1459::line object. +// The top rule is inherited and then specified as grammar::line, which is compatible +// with an rfc1459::line object. +// +struct head +:parse::grammar +{ + head(): grammar{grammar::line} {} +} +const head; + +// Instantiate the input grammar to parse a const char* buffer into an rfc1459::tape object. +// The top rule is now grammar::tape and the target object is an rfc1459::tape deque. +// +struct capstan +:parse::grammar> +{ + capstan(): grammar{grammar::tape} {} +} +const capstan; } // namespace parse } // namespace rfc1459 } // namespace ircd +namespace ircd { +namespace rfc1459 { +namespace gen { + +namespace karma = boost::spirit::karma; +using karma::lit; +using karma::int_; +using karma::char_; +using karma::buffer; +using karma::repeat; + +template +struct grammar +:karma::grammar +{ + std::string trail_save; + + karma::rule space; + karma::rule colon; + karma::rule terminator; + + karma::rule hostname; + karma::rule user; + karma::rule nick; + karma::rule prefix; + karma::rule prefix_optionals; + + karma::rule trailing; + karma::rule middle; + karma::rule params; + + karma::rule command_numeric; + karma::rule command_alpha; + karma::rule command; + karma::rule line; + + grammar(karma::rule &top_rule); +}; + +template +rfc1459::gen::grammar::grammar(karma::rule &top_rule) +:grammar::base_type +{ + top_rule +} +,space // A single space character +{ + lit(' ') + ,"space" +} +,colon // A single colon character +{ + lit(':') + ,"colon" +} +,terminator // The message terminator +{ + lit('\r') << lit('\n') + ,"terminator" +} +,hostname // A valid hostname +{ + +char_(charset(character::HOST)) // TODO: https://tools.ietf.org/html/rfc952 + ,"hostname" +} +,user // A valid username +{ + +char_(charset(character::USER)) + ,"user" +} +,nick // A valid nickname, leading letter followed by any NICK chars +{ + buffer[char_(charset(character::ALPHA)) << *char_(charset(character::NICK))] + ,"nick" +} +,prefix +{ + colon << nick << lit('!') << user << lit('@') << hostname + ,"prefix" +} +,prefix_optionals +{ + colon << (nick | lit('*')) + << lit('!') << (user | lit('*')) + << lit('@') << (hostname | lit('*')) + ,"prefix_optionals" +} +,trailing +{ + colon << +(~char_("\r\n")) + ,"trailing" +} +,middle // Spaced parameters +{ + ~char_(":\x20\r\n") << *(~char_("\x20\r\n")) + ,"middle" +} +,params //TODO: this doesn't work yet, don't use +{ + *(middle % space) << buffer[-trailing] + ,"params" +} +,command_numeric // \d\d\d numeric +{ + repeat(3)[char_(charset(character::DIGIT))] + ,"command_numeric" +} +,command_alpha +{ + +char_(charset(character::ALPHA)) + ,"command_alpha" +} +,command +{ + command_alpha | command_numeric + ,"command" +} +,line +{ + prefix << command << space << params << terminator + ,"line" +} +{ +} + +} // namespace gen +} // namespace rfc1459 +} // namespace ircd + using namespace ircd; //NOTE: unterminated