The Context Policy

| The Context Policy |

> Introduction
> Header 'wave/preprocessing_hooks.hpp' synopsis
> Member functions

## Introduction

The context policy is used to provide callback hooks, which are called from inside the library into the user code, whenever

- a preprocessor directive has been recognized (or not recognized),
- a token is about to be returned from the preprocessor,
- a macro gets defined or undefined,
- a macro has been expanded or rescanned,
- a #line directive is emitted,
- an include file is searched for in the filesystem,
- an include file has been opened or closed,
- a conditional expression was evaluated,
- a token has to be skipped because it is contained in a non-evaluated conditional block, or
- a pragma of the form `'wave option[(value)]'` has been recognized.

This policy type is used as a template parameter to the `boost::wave::context<>` object, where the default policy provides empty hook functions only.

## Header wave/preprocessing_hooks.hpp synopsis

    namespace boost {
    namespace wave {
    namespace context_policies {

        struct default_preprocessing_hooks {

            // general hook functions
            template <typename ContextT, typename TokenT>
            bool found_directive(ContextT const &ctx,
                TokenT const &directive);

            template <typename ContextT, typename ContainerT>
            bool found_unknown_directive(ContextT const& ctx,
                ContainerT const& line, ContainerT& pending);

            template <typename ContextT, typename ExceptionT>
            void throw_exception(ContextT const &ctx,
                ExceptionT const& e);

            // test, whether a given token may be skipped
            template <typename ContextT>
            bool may_skip_whitespace (ContextT const& ctx,
                TokenT &token, bool &skipped_newline);

            // Conditional compilation
            template <
                typename ContextT, typename TokenT,
                typename ContainerT
            >
            bool evaluated_conditional_expression(
                ContextT const &ctx, TokenT const& directive,
                ContainerT const& expression, bool expression_value);

            template <typename ContextT, typename TokenT>
                void skipped_token(ContextT const &ctx,
                TokenT const& token);

            template <typename ContextT, typename TokenT>
            TokenT const& generated_token(ContextT const &ctx,
                TokenT const& token);

            // macro expansion tracing
            template <
                typename ContextT, typename TokenT, typename ContainerT,
                typename IteratorT
            >
            bool expanding_function_like_macro(
                ContextT const &ctx, TokenT const &macrodef,
                std::vector<TokenT> const &formal_args,
                ContainerT const &definition, TokenT const &macrocall,
                std::vector<ContainerT> const &arguments,
                IteratorT const &seqstart, Iterator const &seqend);

            template <typename ContextT, typename TokenT, typename ContainerT>
            bool expanding_object_like_macro(
                ContextT const &ctx, TokenT const &macro,
                ContainerT const &definition, TokenT const &macrocall);

            template <typename ContextT, typename ContainerT>
            void expanded_macro(ContextT const &ctx,
                ContainerT const &result);

            template <typename ContextT, typename ContainerT>
            void rescanned_macro(ContextT const &ctx,
                ContainerT const &result);

            // include file tracing functions
            template <typename ContextT>
            bool found_include_directive(ContextT const &ctx,
                std::string const &filename, bool include_next);

            template <typename ContextT>
            bool locate_include_file(ContextT& ctx, std::string &file_path,
                bool is_system, char const *current_name,
                std::string &dir_path, std::string &native_name);

            template <typename ContextT>
            void opened_include_file(ContextT const &ctx,
                std::string const &relname, std::string const& absname,
                bool is_system_include);

            template <typename ContextT>
            void returning_from_include_file(ContextT const &ctx);

            template <typename ContextT>
            void detected_include_guard(ContextT const &ctx,
                std::string const& filename,
                std::string const& include_guard);

            template <typename ContextT, typename TokenT>
            void detected_pragma_once(ContextT const &ctx,
                TokenT const& pragma_token,
                std::string const& filename);

            // interpretation of #pragmas of the form
            // 'wave option[(value)]'
            template <typename ContextT, typename ContainerT>
            bool interpret_pragma(ContextT const &ctx, ContainerT &pending,
                typename ContextT::token_type const &option,
                ContainerT const &values,
                typename ContextT::token_type const &pragma_token);

            // macro definition hooks
            template <
                typename ContextT, typename TokenT,
                typename ParametersT, typename DefinitionT
            >
            void defined_macro(ContextT const &ctx, TokenT const &name,
                bool is_functionlike, ParametersT const &parameters,
                DefinitionT const &definition, bool is_predefined);

            template <typename ContextT, typename TokenT>
            void undefined_macro(ContextT const &ctx,
                TokenT const &name);

            // #error and #warning directive hooks
            template <typename ContextT, typename ContainerT>
            bool found_warning_directive(ContextT const &ctx,
                ContainerT const &message);

            template <typename ContextT, typename ContainerT>
            bool found_error_directive(ContextT const &ctx,
                ContainerT const &message);

            // #line directive hooks
            template <typename ContextT, typename ContainerT>
            void found_line_directive(ContextT const &ctx,
                ContainerT const &arguments, unsigned int line,
                std::string const& filename);

            template <typename ContextT, typename ContainerT>
            bool emit_line_directive(ContextT const& ctx, ContainerT &pending,
                typename ContextT::token_type const& act_token);

        };

    }}}   // namespace boost::wave::context_policies

## Member functions

### General hook functions

found_directive

        template <typename ContextT, typename TokenT>
        bool found_directive(ContextT const& ctx, TokenT const &directive);

> The function `found_directive` is called, whenever the preprocessor has detected one of the preprocessing directives (#define, #undef, #if, #idef, #ifndef, #elif, #endif, #error, #include, #pragma or #warning) .

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `directive` refers to the token containing the detected preprocessing directive.

> If the return value is `true`, the directive will be skipped altogether, i.e. no preprocessing is done. The overall directive is replaced by a single newline character. If the return value is `false`, the directive is processed in the normal manner.

found_unknown_directive

        template <typename ContextT, typename ContainerT>
        bool found_unknown_directive(ContextT const& ctx,
            ContainerT const& line, ContainerT& pending);

> The function `found_unknown_directive` is called, whenever an unknown preprocessor directive was encountered.

> The parameter `ctx` is a reference to the context object used for instantiating the preprocessing iterators by the user.

> The parameter `line` holds the tokens of the entire source line containing the unknown directive.

> The parameter `pending` may be used to push tokens back into the input stream, which are to be used as the replacement text for the whole line containing the unknown directive.

> The return value defines whether the given expression has been properly interpreted by the hook function or not. If this function returns `false`, the library will raise an `ill_formed_directive` exception. Otherwise the tokens pushed back into `pending` are passed on to the user program.

throw_exception

        template <typename ContextT, typename ExceptionT>
        void throw_exception(ContextT const &ctx,
            ExceptionT const& e);

> The function `throw_exception` is called, whenever a preprocessing exception occurs .

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `e` is the exception object containing detailed error information.

may_skip_whitespace

        template <typename ContextT, typename TokenT>
        bool may_skip_whitespace(ContextT const& ctx, TokenT &token,
            bool& skipped_newline);

> The function `may_skip_whitespace` will be called by the library, whenever a token is about to be returned to the calling application.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user. Note, this parameter was added for the Wave V1.2.4 release.

> The `token` parameter holds a reference to the current token. The policy is free to change this token if needed.

> The `skipped_newline` parameter holds a reference to a boolean value which should be set to true by the policy function whenever a newline is going to be skipped.

> If the return value is `true`, the given token is skipped and the preprocessing continues to the next token. If the return value is `false`, the given token is returned to the calling application. Caution has to be used, because by returning true the policy function is able to force skipping even significant tokens not only whitespace.

### Conditional compilation hook functions

evaluated_conditional_expression

       template <typename ContextT, typename TokenT, typename ContainerT>
        bool evaluated_conditional_expression(ContextT const& ctx,
            TokenT const& directive, ContainerT const& expression,
            bool expression_value);

> The function `evaluated_conditional_expression` is called, whenever the preprocessor has encountered a #if, #elif, #ifdef or #ifndef directive. This hook gets passed the non-expanded conditional expression (as it was given in the analysed source file) and the result of the evaluation of this expression in the current preprocessing context.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The `token` parameter holds a reference to the evaluated directive token.

> The parameter `expression` holds the non-expanded token sequence comprising the evaluated expression.

> The parameter `expression_value` contains the result of the evaluation of the expression in the current preprocessing context.

> The return value defines, whether the given expression has to be evaluated again, allowing to decide which of the conditional branches should be expanded. You need to return 'true' from this hook function to force the expression to be re-evaluated.

skipped_token

        template <typename ContextT, typename TokenT>
        void skipped_token(ContextT const& ctx, TokenT const& token);

> The function `skipped_token` is called, whenever a token is about to be skipped due to a false preprocessor condition (code fragments to be skipped inside the not evaluated conditional #if/#else/#endif branches).

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `token` refers to the token to be skipped.

generated_token

        template <typename ContextT, typename TokenT>
        TokenT const& generated_token(ContextT const& ctx, TokenT const& token);

> The function `generated_token` is called, whenever a token is about to be returned from the library.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `token` refers to the token about to be returned from the library. This function may alter the token, but in this case it must be implemented with a non-const reference for the token parameter, allowing to modify the token in place.

> The default behavior is to return the passed token reference unchanged to the caller.

### Macro expansion tracking functions

expanding_function_like_macro

       template <typename ContextT, typename TokenT, typename ContainerT>
        bool expanding_function_like_macro(
            ContextT const& ctx, TokenT const &macrodef,
            std::vector<TokenT> const &formal_args,
            ContainerT const &definition, TokenT const &macrocall,
            std::vector<ContainerT> const &arguments,
            IteratorT const &seqstart, Iterator const &seqend);

> The function `expanding_function_like_macro` is called, whenever a function-like macro is to be expanded, i.e. before the actual expansion starts.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The `macroname` parameter marks the position where the macro to expand is defined. It contains the token which identifies the macro name used inside the corresponding macro definition.

> The `formal_args` parameter holds the formal arguments used during the definition of the macro.

> The `definition` parameter holds the macro definition for the macro to trace. This is a standard STL container which holds the token sequence identified during the macro definition as the macro replacement list.

> The `macrocall` parameter marks the position where this macro is invoked. It contains the token, which identifies the macro call inside the preprocessed input stream.

> The `arguments` parameter holds the macro arguments used during the invocation of the macro. This is a vector of standard STL containers which contain the token sequences identified at the position of the macro call as the arguments to be used during the macro expansion.

> The parameters `seqstart` and `seqend` point into the input token stream allowing to access the whole token sequence comprising the macro invocation (starting with the opening parenthesis and ending after the closing one).

> If the return value is `true`, the macro is not expanded, i.e. the overall macro invocation sequence, including the parameters are copied to the output without further processing . If the return value is `false`, the macro is expanded as expected.

expanding_object_like_macro

        template <typename ContextT, typename TokenT, typename ContainerT>
        bool expanding_object_like_macro(
            ContextT const& ctx, TokenT const &macro,
            ContainerT const &definition, TokenT const &macrocall);

> The function `expanding_object_like_macro` is called, whenever a object-like macro is to be expanded, i.e. before the actual expansion starts.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The `macroname` parameter marks the position where the macro to expand is defined. It contains the token which identifies the macro name used inside the corresponding macro definition.

> The `definition` parameter holds the macro definition for the macro to trace. This is a standard STL container which holds the token sequence identified during the macro definition as the macro replacement list.

> The `macrocall` parameter marks the position where this macro is invoked. It contains the token which identifies the macro call inside the preprocessed input stream.

> If the return value is `true`, the macro is not expanded, i.e. the macro symbol is copied to the output without further processing. If the return value is `false`, the macro is expanded as expected.

expanded_macro

        template <typename ContextT, typename ContainerT>
        void expanded_macro(ContextT const& ctx, ContainerT const &result);

> The function `expanded_macro` is called whenever the expansion of a macro is finished, the replacement list is completely scanned and the identified macros herein are replaced by its corresponding expansion results, but before the rescanning process starts.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `result` contains the the result of the macro expansion so far. This is a standard STL container containing the generated token sequence.

rescanned_macro

        template <typename ContextT, typename ContainerT>
        void rescanned_macro(ContextT const& ctx, ContainerT const &result);

> The function `rescanned_macro` is called whenever the rescanning of a macro is finished, i.e. the macro expansion is complete.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `result` contains the the result of the whole macro expansion. This is a standard STL container containing the generated token sequence.

### Include file tracing functions

found_include_directive

        template <typename ContextT>
        bool found_include_directive(ContextT const& ctx,
            std::string const &filename, bool include_next);

> The function `found_include_directive` is called whenever whenever a #include directive was located..

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `filename` contains the (expanded) file name found after the #include directive. This has the format `<file>`, `"file"` or `file`. The formats `<file>` or `"file"` are used for #include directives found in the preprocessed token stream, the format `file` is used for files specified through the --force_include command line argument.

> The parameter `include_next` is set to true if the found directive was a #include_next directive and the `BOOST_WAVE_SUPPORT_INCLUDE_NEXT` preprocessing constant was defined to something != 0.

> If the return value is `true`, the include directive is not executed, i.e. the file to include is not loaded nor processed. The overall directive is replaced by a single newline character. If the return value is `false`, the directive is executed in a normal manner.

locate_include_file

        template <typename ContextT>
        bool locate_include_file(ContextT& ctx, std::string &file_path,
            bool is_system, char const *current_name, std::string &dir_path,
            std::string &native_name)

> The function `locate_include_file` is called, whenever a #include directive was encountered. It is supposed to locate the given file and should return the full file name of the located file. This file name is expected to uniquely identify the referenced file.

> The parameter `ctx` is a reference to the context object used for instantiating the preprocessing iterators by the user.

> The parameter `file_path` contains the (expanded) file name found after the `#include` directive. This parameter holds the string as it is specified in the #include directive, i.e. `<file>` or `"file"` will result in a parameter value 'file'.

> The parameter `is_system` is set to `true` if this call happens as a result of a #include <file> directive, it is `false` otherwise, i.e. for #include "file" directives.

> The parameter `current_name` is only used if a #include_next directive was encountered (and `BOOST_WAVE_SUPPORT_INCLUDE_NEXT` was defined to be non-zero). In this case it points to unique full name of the current include file (if any). Otherwise this parameter is set to `NULL`.

> The parameter `dir_path` on return is expected to hold the directory part of the located file.

> The parameter `native_name` on return is expected to hold the unique full file name of the located file.

> The return value defines whether the file was located successfully.

opened_include_file

        template <typename ContextT>
        void opened_include_file(ContextT const& ctx,
            std::string const &rel_filename, std::string const &abs_filename,
            bool is_system_include);

> The function `opened_include_file` is called whenever a file referred by an #include directive was successfully located and opened.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `rel_filename` contains the (normalised) probably relative file system path of the opened file. The concrete format of this file name depends on the format of the include search path given to the library beforehand.

> The parameter `abs_filename` contains the (normalised) full file system path of the opened file.

> The `is_system_include` parameter denotes, if the given file was found as a result of a `#include <...>` directive.

returning_from_include_file

        template <typename ContextT>
        void returning_from_include_file(ContextT const& ctx);

> The function `returning_from_include_file` is called whenever an included file is about to be closed after it's processing is complete.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

detected_include_guard

        template <typename ContextT>
        void detected_include_guard(ContextT const& ctx,
            std::string const& filename,
            std::string const& include_guard);

> The function `detected_include_guard` is called whenever an include file is about to be added to the list of #pragma once headers as the result of a detected include guard scheme. That means this header file will not be opened and parsed again even if it is specified in a later #include directive.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `filename` contains the file system path of the opened file (this is relative to the directory of the currently processed file or a absolute path depending on the paths given as the include search paths).

> The parameter `include_guard` contains the name of the detected include guard.

detected_pragma_once

        template <typename ContextT, typename TokenT>
        void detected_pragma_once(ContextT const& ctx,
            TokenT const& pragma_token,
            std::string const& filename);

> The function `detected_pragma_once` is called whenever either an include file is about to be added to the list of #pragma once headers as the result of a detected #pragma once directive. That means this header file will not be opened and parsed again even if it is specified in a later #include directive.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter pragma_token refers to the token "#pragma" triggering this preprocessing hook.

> The parameter `filename` contains the file system path of the opened file (this is relative to the directory of the currently processed file or a absolute path depending on the paths given as the include search paths).

### Interpretation of #pragmas

interpret_pragma

        template <typename ContextT, typename ContextT, typename ContainerT>
        bool interpret_pragma(ContextT const &ctx, ContainerT &pending,
            typename ContextT::token_type const &option,
            ContainerT const &values,
            typename ContextT::token_type const &pragma_token);

> The function `interpret_pragma` is called whenever an unrecognized `#pragma wave ...` or operator `_Pragma("wave ...")` is found in the input stream.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The `pending` parameter may be used to push tokens back into the input stream which are to be used as the replacement text for the whole `#pragma wave()` directive. If this sequence is left empty, no replacement takes place, i.e. the interpreted directive is removed from the generated token stream.

> The `option` parameter contains the name of the interpreted pragma.

> The `values` parameter holds the value of the parameter provided to the pragma operator.

> The `pragma_token` parameter contains the actual #pragma token which may be used for extraction of the location information for some error output.

> If the return value is 'false', the whole #pragma directive is interpreted as unknown and a corresponding error message is issued. A return value of 'true' signs a successful interpretation of the given #pragma.

### Macro definition

defined_macro

        template <
            typename ContextT, typename TokenT, typename ParametersT,
            typename DefinitionT
        >
        void defined_macro(ContextT const& ctx,
            TokenT const &name, bool is_functionlike,
            ParametersT const &parameters, DefinitionT const &definition,
            bool is_predefined);

> The function `defined_macro` is called whenever a macro was defined successfully.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `name` is a reference to the token holding the macro name.

> The parameter `is_functionlike` is set to true whenever the newly defined macro is defined as a function like macro.

> The parameter `parameters` holds the parameter tokens for the macro definition. If the macro has no parameters or if it is a object like macro, then this container is empty.

> The parameter `definition` contains the token sequence given as the replacement sequence (definition part) of the newly defined macro.

> The parameter `is_predefined` is set to true for all macros predefined during the initialisation pahase of the library.

undefined_macro

        template <typename ContextT, typename TokenT>
        void undefined_macro(ContextT const& ctx, TokenT const &name);

> The function `undefined_macro` is called whenever a macro definition was removed successfully.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `name` holds the token of the macro which definition was removed.

found_warning_directive

        template <typename ContextT, typename ContainerT>
        bool found_warning_directive(ContextT const& ctx,
            ContainerT const &message);

> The function `found_warning_directive` is called whenever a #warning directive has been encountered. This function will be called only if the `BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE` compile time constant was defined to something not equal to zero (see the Compile Time Configuration for more information).

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `message` references the argument token sequence of the encountered #warning directive.

> If the return value is `false`, the library throws a preprocessor exception of the type `warning_directive` (normal execution continues), if the return value is `true` the execution continues as if no #warning directive has been found and the overall directive is replaced by a single newline.

found_error_directive

        template <typename ContextT, typename ContainerT>
        bool found_error_directive(ContextT const& ctx,
            ContainerT const &message);

> The function `found_error_directive` is called whenever a #error directive has been encountered.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `message` references the argument token sequence of the encountered #error directive.

> If the return value is `false`, the library throws a preprocessor exception of the type `error_directive` (normal execution continues), if the return value is `true` the execution continues as if no #error directive has been found, and the overall directive is replaced by a single newline.

found_line_directive

        template <typename ContextT, typename ContainerT>
        void found_line_directive(ContextT const& ctx,
            ContainerT const &arguments, unsigned int line,
            std::string const& filename);

> The function `found_line_directive` is called whenever a #line directive has been encountered.

> The `ctx` parameter provides a reference to the `context_type` used during instantiation of the preprocessing iterators by the user.

> The parameter `arguments` references the argument token sequence of the encountered #line directive.

> The parameter `line` contains the recognized line number from the #line directive.

> The parameter `filename` references the recognized file name from the #line directive (if there was one given).

emit_line_directive

        template <typename ContextT, typename ContainerT>
        bool emit_line_directive(ContextT const& ctx, ContainerT &pending,
            typename ContextT::token_type const& act_token);

> The function `emit_line_directive` is called whenever a #line directive has to be emitted into the generated output.

> The parameter `ctx` is a reference to the context object used for instantiating the preprocessing iterators by the user.

> The parameter `pending` may be used to push tokens back into the input stream, which are to be used instead of the default output generated for the #line directive.

> The parameter `act_token` contains the actual #pragma token, which may be used for error output. The line number stored in this token can be used as the line number emitted as part of the #line directive.

> If the return value is `false`, a default #line directive is emitted by the library. A return value of `true` will inhibit any further actions, the tokens contained in `pending` will be copied verbatim to the output.

Copyright © 2003-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Last updated: Thursday, September 18, 2010 09:10