/*description:
{
    Script that operates the transformation of a C++ source file to insert profiling code
    in the body of functions.

    Here, no parsing is processed for recognizing the signature of functions and the body.
    So, some troubles might appear if a \samp{\#define} macro describes a part or the whole
    of the function.

    One activates the profiling by setting the preprocessor definition \textbf{RAW_PROFILING}
    at compile-time (\samp{-D RAW_PROFILING} on the command line of the C++ compiler).

    To make it simple, the header of the \textit{profiling module} is inserted after the first
    \samp{\#include} encountered. It may cause some troubles if the first include is put in
    a conditional preprocessing block (\samp{\#ifdef WIN32} ... \samp{\#endif}/\samp{\#else}).

    The body of the function starts by incrementing its assigned counter held by the
    \textit{profiling module} and by timing the visit of the controlled sequence.

    Note that the transformation can be applied more than once: the second pass will not
    affect the source file.
}
*/

#implicitCopy

profiling ::=
    #ignore(C++) // ignore C++/JAVA-like comments
    [insert_include]?
    [
        => local sName1;
        => local sName2;
        => local sPrefix2;
        => local bNewLine;
        ->[
            #readCompleteIdentifier:sName1
            [
                    "::"
                    ['~' => sPrefix2 = "destructor_"; | => sPrefix2 = "";]
                    #readIdentifier:sName2
                    => set sName2 = sPrefix2 + sName2;
                |
                    => set sName2 = "";
            ]?
            #check(sName2 || ((sName1 != "if") && (sName1 != "while") && (sName1 != "catch")))
            '('
            [parameter_token_list]?
            ')'
            [post_function_token_decl]?
            [':' constructor_initialization_token_list | !':']
            '{' #!ignore ignoreLineBlanks
            ['\n' | => set bNewLine = true;]
            !"#ifdef RAW_PROFILING"
        ] => {
            if bNewLine {
                @@endl()@@
            }
            local sKey = sName1 + "_" + sName2;
            insert this.listOfKeys[sKey] = sKey;
            if sName2 {
                insert this.listOfKeys[sKey].class = sName1;
                insert this.listOfKeys[sKey].name = sName2;
            } else {
                insert this.listOfKeys[sKey].name = sName1;
            }
            @#ifdef RAW_PROFILING
    RawProfiling::RawProfiling::@sKey@_counter++;
    RawProfiling::RawProfiling theProfiling(RawProfiling::RawProfiling::@sKey@_chronograph);
#endif
@
        }
    ]*
    ->#empty;

insert_include    ::=
        ![->["#ifdef" "RAW_PROFILING" '#' "include"]]
        ->["#include" #!ignore ->'\n']
        => {
            @
#ifdef RAW_PROFILING
#    include "RawProfiling.h"
#endif

@
        };

parameter_token_list ::= parameter_tokens [',' parameter_tokens]*;
parameter_tokens ::=
        [
            #readIdentifier | '[' | ']' |
            '.' | // JAVA only
            #readInteger | '*' | '&' | "::" // C++ only
        ]+;

post_function_token_decl ::= [#readIdentifier | '(' post_function_token_decl ')' | '.' | "::"]+;

constructor_initialization_token_list    ::= constructor_initialization_tokens [',' constructor_initialization_tokens]*;
constructor_initialization_tokens    ::= #readIdentifier '(' expression ')';

expression    ::=
        [[~['[' | ']' '(' | ')' | '{' | '}' | ',']]+ | '[' expression ']' | '(' expression ')']+;

ignoreLineBlanks : #!ignore    ::= ["//" [~'\n']* | '\t' | ' ' | '\r']*;

Generated by v4.5.3 from CWscript2HTML.cwp.