/* file: dbg_macros.h */
/*
DBG_L0   exits
DBG_L1   exits + calls
DBG_L2   exits + calls + returns               (value)
DBG_L3   exits + calls + returns               (address)
DBG_L4   exits + calls + returns               (value + address)
DBG_L5   exits + calls + returns + args        (value)
DBG_L6   exits + calls + returns + args        (address)
DBG_L7   exits + calls + returns + args        (value + address)
DBG_L8   exits + calls + returns + args + vars (value)
DBG_L9   exits + calls + returns + args + vars (address)
DBG_LA   exits + calls + returns + args + vars (value + address)
*/



#ifndef _DBG_MACROS_H
    #define _DBG_MACROS_H 1U
 
    #include <stdio.h>
    #include <stdlib.h>
 
 
 
        #define __PRINT_HEADING( HEADING_STR,                                                            \
                                 SPACE_NUM )                                                             \
                    printf( "\t" HEADING_STR  "%" #SPACE_NUM "s" "file:      %s"               "\n"      \
                            "\t" "          " "%" #SPACE_NUM "s" "function:  %s"               "\n",     \
                            "",                                                                          \
                            __FILE__,                                                                    \
                            "",                                                                          \
                            __FUNC__ )
 
        #define __PRINT_NAME( SPACE_NUM,                                                                 \
                              NAME )                                                                     \
                    printf( "\t" "          " "%" #SPACE_NUM "s" "name:      "   #NAME         "\n",     \
                            "" )
 
        #define __PRINT_LINE( SPACE_NUM )                                                                \
                    printf( "\t" "          " "%" #SPACE_NUM "s" "line:      %d"               "\n",     \
                            "",                                                                          \
                            __LINE__ )

        #if ( defined( DBG_L0 ) ||                                                                       \
              defined( DBG_L1 ) ||                                                                       \
              defined( DBG_L2 ) ||                                                                       \
              defined( DBG_L4 ) ||                                                                       \
              defined( DBG_L5 ) ||                                                                       \
              defined( DBG_L7 ) ||                                                                       \
              defined( DBG_L8 ) ||                                                                       \
              defined( DBG_LA ) )
            #define __PRINT_VALUE( SPACE_NUM,                                                            \
                                   CONV_SPEC_STR,                                                        \
                                   VALUE )                                                               \
                        printf( "\t" "          " "%" #SPACE_NUM "s" "value:     %"  CONV_SPEC_STR "\n", \
                                "",                                                                      \
                                VALUE )
        #else
            #define __PRINT_VALUE( SPACE_NUM,                                                            \
                                   CONV_SPEC_STR,                                                        \
                                   VALUE )
        #endif

        #if ( defined( DBG_L3 ) ||                                                                       \
              defined( DBG_L4 ) ||                                                                       \
              defined( DBG_L6 ) ||                                                                       \
              defined( DBG_L7 ) ||                                                                       \
              defined( DBG_L9 ) ||                                                                       \
              defined( DBG_LA ) )
            #define __PRINT_ADDRESS( SPACE_NUM,                                                          \
                                     ADDRESS )                                                           \
                        printf( "\t" "          " "%" #SPACE_NUM "s" "address:   %p"               "\n", \
                                "",                                                                      \
                                (void *)ADDRESS )
        #else
            #define __PRINT_ADDRESS( SPACE_NUM,                                                          \
                                     ADDRESS )
        #endif
 
        #if ( defined( DBG_L0 ) ||                                                                       \
              defined( DBG_L1 ) ||                                                                       \
              defined( DBG_L2 ) ||                                                                       \
              defined( DBG_L3 ) ||                                                                       \
              defined( DBG_L4 ) ||                                                                       \
              defined( DBG_L5 ) ||                                                                       \
              defined( DBG_L6 ) ||                                                                       \
              defined( DBG_L7 ) ||                                                                       \
              defined( DBG_L8 ) ||                                                                       \
              defined( DBG_L9 ) ||                                                                       \
              defined( DBG_LA ) )
            #define SET_FUNC_NAME( FUNC )                                                                \
                        const char *__FUNC__ = #FUNC
        #else
            #define SET_FUNC_NAME( FUNC )
        #endif
 
        #if ( defined( DBG_L1 ) ||                                                                       \
              defined( DBG_L2 ) ||                                                                       \
              defined( DBG_L3 ) ||                                                                       \
              defined( DBG_L4 ) ||                                                                       \
              defined( DBG_L5 ) ||                                                                       \
              defined( DBG_L6 ) ||                                                                       \
              defined( DBG_L7 ) ||                                                                       \
              defined( DBG_L8 ) ||                                                                       \
              defined( DBG_L9 ) ||                                                                       \
              defined( DBG_LA ) )
            #define CALL_DUMP()                                                                          \
                        __PRINT_HEADING( "[DBG|CALL]",                                                   \
                                         1 )
        #else
            #define CALL_DUMP()
        #endif

        #if ( defined( DBG_L5 ) ||                                                                       \
              defined( DBG_L6 ) ||                                                                       \
              defined( DBG_L7 ) ||                                                                       \
              defined( DBG_L8 ) ||                                                                       \
              defined( DBG_L9 ) ||                                                                       \
              defined( DBG_LA ) )
            #define ARG_DUMP( ARG,                                                                       \
                              CONV_SPEC_STR )                                                            \
                        do                                                                               \
                        {                                                                                \
                            __PRINT_HEADING( "[ DBG|ARG]",                                               \
                                             2 );                                                        \
                            __PRINT_NAME( 2,                                                             \
                                          ARG );                                                         \
                            __PRINT_VALUE( 2,                                                            \
                                           CONV_SPEC_STR,                                                \
                                           ARG );                                                        \
                            __PRINT_ADDRESS( 2,                                                          \
                                             &ARG );                                                     \
                        } while ( 0 )
 
            #define PTRARG_DUMP( ARG,                                                                    \
                                 CONV_SPEC_STR )                                                         \
                        do                                                                               \
                        {                                                                                \
                            __PRINT_HEADING( "[ DBG|ARG]",                                               \
                                             2 );                                                        \
                            __PRINT_NAME( 2,                                                             \
                                          ARG );                                                         \
                            __PRINT_VALUE( 2,                                                            \
                                           CONV_SPEC_STR,                                                \
                                           *ARG );                                                       \
                            __PRINT_ADDRESS( 2,                                                          \
                                             ARG );                                                      \
                        } while ( 0 )
        #else
            #define ARG_DUMP( ARG,                                                                       \
                              CONV_SPEC_STR )
 
            #define PTRARG_DUMP( ARG,                                                                    \
                                 CONV_SPEC_STR )
        #endif

        #if ( defined( DBG_L8 ) ||                                                                       \
              defined( DBG_L9 ) ||                                                                       \
              defined( DBG_LA ) )
            #define VAR_DUMP( VAR,                                                                       \
                              CONV_SPEC_STR )                                                            \
                        do                                                                               \
                        {                                                                                \
                            __PRINT_HEADING( "[ DBG|VAR]",                                               \
                                             2 );                                                        \
                            __PRINT_NAME( 2,                                                             \
                                          VAR );                                                         \
                            __PRINT_VALUE( 2,                                                            \
                                           CONV_SPEC_STR,                                                \
                                           VAR );                                                        \
                            __PRINT_ADDRESS( 2,                                                          \
                                             &VAR );                                                     \
                        } while ( 0 )
 
            #define PTRVAR_DUMP( VAR,                                                                    \
                                 CONV_SPEC_STR )                                                         \
                        do                                                                               \
                        {                                                                                \
                            __PRINT_HEADING( "[ DBG|VAR]",                                               \
                                             2 );                                                        \
                            __PRINT_NAME( 2,                                                             \
                                          VAR );                                                         \
                            __PRINT_VALUE( 2,                                                            \
                                           CONV_SPEC_STR,                                                \
                                           *VAR );                                                       \
                            __PRINT_ADDRESS( 2,                                                          \
                                             VAR );                                                      \
                        } while ( 0 )
        #else
            #define VAR_DUMP( VAR,                                                                       \
                              CONV_SPEC_STR )
 
            #define PTRVAR_DUMP( VAR,                                                                    \
                                 CONV_SPEC_STR )
        #endif
 
        #if ( defined( DBG_L2 ) ||                                                                       \
              defined( DBG_L3 ) ||                                                                       \
              defined( DBG_L4 ) ||                                                                       \
              defined( DBG_L5 ) ||                                                                       \
              defined( DBG_L6 ) ||                                                                       \
              defined( DBG_L7 ) ||                                                                       \
              defined( DBG_L8 ) ||                                                                       \
              defined( DBG_L9 ) ||                                                                       \
              defined( DBG_LA ) )
            #define RET_DUMP( RET,                                                                       \
                              CONV_SPEC_STR )                                                            \
                        do                                                                               \
                        {                                                                                \
                            __PRINT_HEADING( "[DBG|RET ]",                                               \
                                             1 );                                                        \
                            __PRINT_LINE( 1 );                                                           \
                            __PRINT_VALUE( 1,                                                            \
                                           CONV_SPEC_STR,                                                \
                                           (RET) );                                                      \
                            __PRINT_ADDRESS( 1,                                                          \
                                             &(RET) );                                                   \
                                                                                                         \
                            return RET;                                                                  \
                        } while ( 0 )
 
            #define PTRRET_DUMP( RET,                                                                    \
                                 CONV_SPEC_STR )                                                         \
                        do                                                                               \
                        {                                                                                \
                            __PRINT_HEADING( "[DBG|RET ]",                                               \
                                             1 );                                                        \
                            __PRINT_LINE( 1 );                                                           \
                            __PRINT_VALUE( 1,                                                            \
                                           CONV_SPEC_STR,                                                \
                                           *(RET) );                                                     \
                            __PRINT_ADDRESS( 1,                                                          \
                                             (RET) );                                                    \
                                                                                                         \
                            return RET;                                                                  \
                        } while ( 0 )
        #else
            #define RET_DUMP( RET,                                                                       \
                              CONV_SPEC_STR )                                                            \
                        return RET
 
            #define PTRRET_DUMP( RET,                                                                    \
                                 CONV_SPEC_STR )                                                         \
                        return RET
        #endif
 
        #if ( defined( DBG_L0 ) ||                                                                       \
              defined( DBG_L1 ) ||                                                                       \
              defined( DBG_L2 ) ||                                                                       \
              defined( DBG_L3 ) ||                                                                       \
              defined( DBG_L4 ) ||                                                                       \
              defined( DBG_L5 ) ||                                                                       \
              defined( DBG_L6 ) ||                                                                       \
              defined( DBG_L7 ) ||                                                                       \
              defined( DBG_L8 ) ||                                                                       \
              defined( DBG_L9 ) ||                                                                       \
              defined( DBG_LA ) )
            #define EXIT_DUMP( EXIT )                                                                    \
                        do                                                                               \
                        {                                                                                \
                            __PRINT_HEADING( "[DBG|EXIT]",                                               \
                                             1 );                                                        \
                            __PRINT_LINE( 1 );                                                           \
                            __PRINT_VALUE( 1,                                                            \
                                           "d",                                                          \
                                           (EXIT) );                                                     \
                                                                                                         \
                            exit( EXIT );                                                                \
                        } while ( 0 )
        #else
            #define EXIT_DUMP( EXIT )                                                                    \
                        exit( EXIT )
        #endif
 
#endif
 
 
 
/* file: test.c */
#define DBG_LA



int operations( int   a, 
                int   b, 
                int * mul )
{
    int add;
 
 
    SET_FUNC_NAME( operations );
    CALL_DUMP();
    ARG_DUMP( a, "d" );
    ARG_DUMP( b, "d" );
    PTRARG_DUMP( mul, "d" );
 
    add = a + b;
    *mul = a * b;
 
 
    RET_DUMP( add, "d" );
}
 
 
 
int main( void )
{
    int a;
    int b;
    int add;
    int mul;
 
 
    SET_FUNC_NAME( main );
    CALL_DUMP();
 
    a = 3;
    b = 2;
    add = 0;
    mul = 0;
    add = operations(  a, 
                   b, 
                  &mul );
 
 
    EXIT_DUMP( 0 );
}
