// $Id$ // // Copyright (C) 2008 // Fraunhofer Institute for Open Communication Systems (FOKUS) // // The contents of this file are subject to the Fraunhofer FOKUS Public License // Version 1.0 (the "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // http://senf.berlios.de/license.html // // The Fraunhofer FOKUS Public License Version 1.0 is based on, // but modifies the Mozilla Public License Version 1.1. // See the full license text for the amendments. // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License // for the specific language governing rights and limitations under the License. // // The Original Code is Fraunhofer FOKUS code. // // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. // (registered association), Hansastraße 27 c, 80686 Munich, Germany. // // Contributor(s): // Stefan Bund /** \page parsermacro_expand_example Example macro-expansion of packet parser helper macros Debugging the packet parser makros is somwhat difficult since the makro expansion will place everything in a single line. To help pin down problems, I use
    $ g++ -DSENF_MPL_SLOT_NOEXPAND -o .ii -E -DSENF_DEBUG -Iinclude .cc
    $ sed -i -e 's/}/}\\n/g' -e '/^#.*$/d' .ii
    $ astyle --style=linux -b .ii
    
I normally just cut-and-paste the \c g++ command from a normal build and add -DSENF_MPL_SLOT_NOEXPAND. \c astyle is found at http://astyle.sourceforge.net/. If needed, I then reissue this file (the precessed \.ii file) back to the compiler using the original commandline (just replacing the \c .cc with \c .ii) to get error messages with meaningful line numbers. The following packet parser definition (taken from VariantParser.test.cc) has been subject to macro-expansion (and a lot of manual reformatting) to show the inner workings of the packet parser macros: \code struct TestParser : public senf::PacketParserBase { # include SENF_PARSER() SENF_PARSER_SKIP_BITS( 4 ); SENF_PARSER_BITFIELD_RO( type, 4, unsigned ); SENF_PARSER_PRIVATE_VARIANT( content_, type, ( novalue( nocontent, key(10, senf::VoidPacketParser)) ) ( id( content, SubParser ) ) ); SENF_PARSER_FINALIZE(TestParser); }; \endcode Here the reformated and sparsly commented expansion. I have left all the \c SENF_MPL_SLOT_ calls unexpanded, otherwise the code would be absolutely unreadable. This is quite a lot of source-code which however should create only a small amount of additional compiled code. Also remember, that all this code is generated by C++ makros. Some detours are needed to work around makro problems (e.g. templates with multiple arguments are parsed as seperate makro arguments at each komma, inability to redefine a makro from another makro ...). \code struct TestParser : public senf::PacketParserBase { //-///////////////////////////////////////////////////////////////////////// // #include SENF_PARSER() private: SENF_MPL_SLOT_INIT_ZERO(index); SENF_MPL_SLOT_INIT_ZERO(init_bytes); SENF_MPL_SLOT_INIT_ZERO(bit); SENF_MPL_SLOT_INIT_ZERO(bitfield_size); SENF_MPL_SLOT_INIT_ZERO(group); void init_chain (senf::mpl::rv <0> *) const {} size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; } //-///////////////////////////////////////////////////////////////////////// // SENF_PARSER_SKIP_BITS( 4 ); SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + 4); //-///////////////////////////////////////////////////////////////////////// // SENF_PARSER_BITFIELD_RO( type, 4, unsigned ); public: static size_type const type_bit = SENF_MPL_SLOT_GET(bit); private: SENF_MPL_SLOT_SET(bit, type_bit + 4); typedef senf::UIntFieldParser type_bit_t; public: typedef type_bit_t type_t; static size_type const type_index = SENF_MPL_SLOT_GET(index) + 1; private: SENF_MPL_SLOT_SET(index, type_index); void init_chain (senf::mpl::rv *) const { init_chain (static_cast *>(0)); } public: size_type type_offset() const { return field_offset_(static_cast *>(0)) - SENF_MPL_SLOT_GET(bitfield_size); } static size_type const type_init_bytes = SENF_MPL_SLOT_GET(init_bytes) - SENF_MPL_SLOT_GET(bitfield_size); size_type type_next_offset () const { return type_offset() + type_t::fixed_bytes; } static size_type const type_next_init_bytes = type_init_bytes + type_t::fixed_bytes; private: size_type field_offset_(senf::mpl::rv *) const { return type_next_offset(); } SENF_MPL_SLOT_SET(init_bytes, type_next_init_bytes); static size_type const type_group = SENF_MPL_SLOT_GET(group) + 0; SENF_MPL_SLOT_SET(group, type_group); SENF_MPL_SLOT_SET(bitfield_size, type_t::fixed_bytes); type_t type_() const { return parse (type_offset ()); } public: type_t::value_type type() const { return type_(); } //-///////////////////////////////////////////////////////////////////////// // SENF_PARSER_PRIVATE_VARIANT( content_, type, // ( novalue( nocontent, key(10, senf::VoidPacketParser)) ) // ( id( content, SubParser ) ) // ); private: typedef boost::mpl::vector content__parsers; typedef type_t::value_type content__chooser_value_type; static content__chooser_value_type content__key_0 () { return 10; } static content__chooser_value_type content__key_1 () { return 1; } template struct content__key_value_template : public senf::detail::VariantKey {}; template friend class senf::detail::VariantKey; typedef senf::detail::VariantKeyTransform< content__chooser_value_type, boost::mpl::vector< content__key_value_template<&content__key_0>, content__key_value_template<&content__key_1> > > content__transform; typedef senf::detail::VariantParserTraits content__traits; // start SENF_PARSER_COLLECTION_I static bool const content__aux_fixed = (SENF_MPL_SLOT_GET(group) - type_group) == 0; typedef senf::detail::ParserAuxPolicySelect < type_t, SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes, content__aux_fixed >::type content__aux_policy; typedef content__traits::parser::type content__collection_t; SENF_MPL_SLOT_SET(bit, 0); SENF_MPL_SLOT_SET(bitfield_size, 0); typedef content__collection_t content__t; static size_type const content__index = SENF_MPL_SLOT_GET(index) + 1; SENF_MPL_SLOT_SET(index, content__index); void init_chain (senf::mpl::rv *) const { init_chain (static_cast *>(0)); content_().init(); } size_type content__offset() const { return field_offset_ (static_cast *>(0)); } static size_type const content__init_bytes = SENF_MPL_SLOT_GET(init_bytes); size_type content__next_offset () const { return content__offset() + senf::bytes(content__()); } static size_type const content__next_init_bytes = content__init_bytes + senf::init_bytes::value; size_type field_offset_(senf::mpl::rv *) const { return content__next_offset(); } SENF_MPL_SLOT_SET(init_bytes, content__next_init_bytes); static size_type const content__group = SENF_MPL_SLOT_GET(group) + (senf::is_fixed::value ? 0 : 1); SENF_MPL_SLOET_SET(group, content__group); template < class T > T content__dispatch (boost::true_type) const { return parse(content__offset()); } template < class T > T content__dispatch(boost::false_type) const { return parse(type(), content__offset()); } content__t content__() const { return content__dispatch( boost::integral_constant()); } content__t content_() const { return content__ (); } // end SENF_PARSER_COLLECTION_I public: void nocontent() const { content_().init<0>(); } typedef SubParser content_t; SubParser content() const { return content_().get<1>(); } void init_content() const { content_().init<1>(); } bool has_content() const { return content_().variant() == 1; }; //-///////////////////////////////////////////////////////////////////////// // SENF_PARSER_FINALIZE(TestParser); void defaultInit() const { init_chain(static_cast *>(0)); } TestParser(data_iterator i, state_type s) : parser_base_type (i, s) {} private: template void init(T) const { defaultInit (); } public: void init() const { init (0); } size_type bytes() const { return field_offset_(static_cast *>(0)); } static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes); }; \endcode */ // Local Variables: // mode: c++ // fill-column: 100 // comment-column: 40 // c-file-style: "senf" // indent-tabs-mode: nil // ispell-local-dictionary: "american" // compile-command: "scons -u test" // mode: flyspell // mode: auto-fill // End: