2

I am trying to implement VERSION macro for my program, that is to be changed under certain circumstances.

macro VERSION is defined via Makefile (git info is put there) and is a string. Now I have a set of #define'd switches and I want VERSION to reflect which of them are on. This looks now like the follows (main.h):

#define COMPLEX_DEPOSITION // This is switch. later in code it is used in #ifdef...#endif construction.

#ifdef COMPLEX_DEPOSITION
#define CD "_COMP_DEP" // this is the string I want to put in the end of VERSION
#define VERSION_ VERSION CD

#undef VERSION // this is to suppress 'macro redefinition' warning
#define VERSION VERSION_
#undef VERSION_
#endif

Well, I get a lot of errors, most of which make me think that C preprocessor works with lines in file in random order:(

Later I have an even more complex thing that is intended to make VERSION -> VERSION_WLT_GAP_2

#define WIRESLIFETIMES

#ifdef WIRESLIFETIMES
#define GAP 2
#define VERSION_ (VERSION ## "_WLT_GAP_" ## #GAP)
#define VERSION VERSION_
#undef VERSION_
#endif

and I got no idea what to do and if this is even possible

Xtotdam
  • 31
  • 4
  • 1
    I suspect the easiest solution is `#else #define CD ""`- always concatenate the same macro's, but just define them to empty strings if not needed. – MSalters Jun 24 '19 at 11:16
  • 2
    https://stackoverflow.com/questions/5256313/c-c-macro-string-concatenation/5256500 – Sir Jo Black Jun 24 '19 at 11:22
  • @SirJoBlack Thank you, I have seen this question and its solution does not work for me. – Xtotdam Jun 24 '19 at 11:33
  • @MSalters Thank you, this solves the first problem but does not solve the second one – Xtotdam Jun 24 '19 at 11:38
  • The problem with the second example appears to be circular logic. `VERSION_` is defined in terms of `VERSION` and `VERSION is then defined as `VERSION_`. I don't even understand the real intent there. – MSalters Jun 24 '19 at 11:55
  • @MSalters seems to be so, I begin thinking that C macros are more sophisticated than they look. I use your idea in my own answer though – Xtotdam Jun 24 '19 at 12:15
  • @Xtotdam: They're certainly very different from regular code. If you look at C++, it still supports macro's for compatibility with C, but C++ strives to develop better alternatives for every use of macro's. – MSalters Jun 24 '19 at 12:17

2 Answers2

5

String literals concatenate naturally when placed next to each other

"foo" "bar" is the same as "foobar".

As for the second example, you probably want:

#define CAT_(A,B) A##B
#define CAT(A,B) CAT_(A,B)

#define GAP 2
#define VERSION CAT(VERSION_WLT_GAP_ , GAP)

VERSION //expands to VERSION_WLT_GAP_2

I recommend playing with gcc -E/clang -E a bit, to learn how macros work, before trying to compose anything complex with them.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • Thank you, but point is that VERSION macro holds a value that comes from Makefile – Xtotdam Jun 24 '19 at 11:52
  • @Xtotdam Conditionally (`#if`) `#undef` it, then? I'm not proposing you make it as simple as this. I'm just presenting the core technique you could use. – Petr Skocik Jun 24 '19 at 11:58
1

Well, the answer seems to be the following:

// https://stackoverflow.com/questions/5256313/c-c-macro-string-concatenation
// Concatenate preprocessor tokens A and B without expanding macro definitions (however, if invoked from a macro, macro arguments are expanded).
#define PPCAT_NX(A, B) A ## B

// Concatenate preprocessor tokens A and B after macro-expanding them.
#define PPCAT(A, B) PPCAT_NX(A, B)

// Turn A into a string literal without expanding macro definitions (however, if invoked from a macro, macro arguments are expanded).
#define STRINGIZE_NX(A) #A

// Turn A into a string literal after macro-expanding it.
#define STR(A) STRINGIZE_NX(A)


#define COMPLEX_DEPOSITION

#ifdef COMPLEX_DEPOSITION
#define CD "_COMPDEP"
#else
#define CD ""
#endif


#define WIRESLIFETIMES

#ifdef WIRESLIFETIMES
#define GAP 2
#define WLT STR(PPCAT(_WLT:G, GAP))
#define DISABLE_METROPOLIS
#else
#define WLT ""
#endif

#define VERSION VERSIONX CD WLT

which produces V008.1-11-g68a9c89cb4-dirty_COMPDEP_WLT:G2 and I am happy with it.

Must be noted that I changed -DVERSION=... to -DVERSIONX=... inside Makefile

Xtotdam
  • 31
  • 4