A macro that defines new macros with an added prefix

We have a profiling structure that can be turned on and off at compile time.

All various infrastructure calls are made using macros, for example:

PROFILE_START(msg)
PROFILE_END(msg)

The macros then allow the actual profiler call when profiling is enabled and nothing is disabled.

#ifdef PROFILING_ENABLED
#    define PROFILE_START(msg) currentProfiler().start(msg)
#    define PROFILE_END(msg)   currentProfiler().end(msg)
#else
#    define PROFILE_START(msg)
#    define PROFILE_END(msg)   
#endif

There are different components in our structure, and I want to include profiling in each component.

I would like to be able to selectively include profiling in each component.

My idea is to prefix all profiler macros with the component name, for example:

FOO_PROFILE_START(msg)
FOO_PROFILE_END(msg)

BAR_PROFILE_START(msg)
BAR_PROFILE_END(msg)

I could manually create

#ifdef ENABLE_FOO_PROFILING
#    define FOO_PROFILE_START(msg) PROFILE_START(msg)
#    define FOO_PROFILE_END(msg) PROFILE_END(msg)
#else
#    define FOO_PROFILE_START(msg) 
#    define FOO_PROFILE_END(msg) 
#endif

#ifdef ENABLE_BAR_PROFILING
#    define BAR_PROFILE_START(msg) PROFILE_START(msg)
#    define BAR_PROFILE_END(msg) PROFILE_END(msg)
#else
#    define BAR_PROFILE_START(msg) 
#    define BAR_PROFILE_END(msg) 
#endif

However, this is tiring and error prone.

, , , , .

, , - .

#ifdef ENABLE_FOO_PROFILING
    ADD_PREFIX_TO_ENABLED_PROFILING_MACROS(FOO)
#else
    ADD_PREFIX_TO_DISABLED_PROFILING_MACROS(FOO)
#endif

FOO_PROFILE_XXX, .

:

  • ?
  • , ?

BOOST_PP, .


, , , , , , , .

#include <stdio.h>

#define PROFILE_START(msg) printf("start(%s)\n", msg);
#define PROFILE_END(msg)   printf("end(%s)\n", msg);

#define ENABLE(prefix) \
    #define prefix ## _PROFILE_START PROFILE_START \
    #define prefix ## _PROFILE_END   PROFILE_END

#define DISABLE(prefix) \
    #define prefix ## _PROFILE_START \
    #define prefix ## _PROFILE_END

#define ENABLE_FOO

#ifdef ENABLE_FOO
    ENABLE(FOO)
#else
    DISABLE(FOO)
#endif

#ifdef ENABLE_BAR
    ENABLE(BAR)
#else
    DISABLE(BAR)
#endif


int main()
{
    FOO_PROFILE_START("foo");
    FOO_PROFILE_END("foo");

    BAR_PROFILE_START("bar");
    BAR_PROFILE_END("bar");

    return 0;
}
+4
3
?

. , .

- , . , , / .

( , .. ), .

1: C

:

#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(_,X,...) X
#define SWITCH(PREFIX_,PATTERN_,DEFAULT_) SECOND(GLUE(PREFIX_,PATTERN_),DEFAULT_)
#define EAT(...)

#define PROFILER_UTILITY(MODULE_) SWITCH(ENABLE_PROFILER_FOR_,MODULE_,DISABLED)
#define PROFILER_IS_DISABLED ,EAT
#define PROFILE_START_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START)(msg)
#define PROFILE_END_FOR(MODULE_, msg)   SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_END)(msg)

... , :

PROFILE_START_FOR(FOO,msg)
PROFILE_END_FOR(FOO,msg)
PROFILE_START_FOR(BAR,msg)
PROFILE_END_FOR(BAR,msg)
PROFILE_START_FOR(BAZ,msg)
PROFILE_END_FOR(BAZ,msg)

; , ENABLE_PROFILER_FOR_xxx FOO, BAR BAZ, , ( ,ON, ), (, ) PROFILE_START(msg)/PROFILE_END(msg); .

FOO , " ": #define ENABLE_PROFILER_FOR_FOO ,ON; : ... -DENABLE_PROFILER_FOR_FOO=,ON; make ; CFLAGS += -DENABLE_PROFILER_FOR_FOO=,ON.

2a: ; SWITCH

#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(_,X,...) X
#define SWITCH(PREFIX_,PATTERN_,DEFAULT_) SECOND(GLUE(PREFIX_,PATTERN_),DEFAULT_)

GLUE ( ). SECOND - , .

SWITCH - . , . ; - , , , , . :

#define ORDINAL(N_) GLUE(N_, SWITCH(ORDINAL_SUFFIX_,N_,th))
#define ORDINAL_SUFFIX_1 ,st
#define ORDINAL_SUFFIX_2 ,nd
#define ORDINAL_SUFFIX_3 ,rd
ORDINAL(1) ORDINAL(2) ORDINAL(3) ORDINAL(4) ORDINAL(5) ORDINAL(6)

... :

1st 2nd 3rd 4th 5th 6th

, SWITCH switch; "" .

, , ( , , , ). SWITCH , PREFIX_/PATTERN_ ( , ).

2b:

case, - ; (, "" "" ), SWITCH . .

:

#define PROFILER_UTILITY(MODULE_) SWITCH(ENABLE_PROFILER_FOR_,MODULE_,DISABLED)
#define PROFILER_IS_DISABLED ,EAT
#define PROFILE_START_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START)(msg)
#define PROFILE_END_FOR(MODULE_, msg)   SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_END)(msg)

... PROFILER_UTILITY . DISABLED. SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START) PROFILER_IS_DISABLED, EAT. PROFILER_UTILITY, , PROFILE_START. PROFILE_END_FOR .

EAT (msg) ; .

, ?

, . , C.

+1

-

#include <stdio.h>

#define FOO_ENABLED 1
#define BAR_ENABLED 0

#define PROFILE_START(FLAG, msg) \
   { if (FLAG) printf("start(%s)\n", msg); }

int main()
{
    PROFILE_START(FOO_ENABLED, "foo")
    PROFILE_START(BAR_ENABLED, "bar")
    return 0;
}

if.

+1
  • ?

. , . *

  • , ?

, * , , . , - , C ( , ), . ​​ - C, python, perl, shell script, . - XSLT.

Each source file that wants to get profiling macros, then just a #includegenerated header.


* In fact, you can use the C preprocessor by running a separate stand-alone launch in a different, input target file. But you cannot generate macros in place when you compile the source file (s) that wants to use them.

0
source

Source: https://habr.com/ru/post/1677933/


All Articles