how to compare in #if condition of preprocessor for string - c-preprocessor

Hi my c code need to consider block of code depending on
#if <condition>
//code block to execute if conditions matches
#endif
Now problem is in my shell script which I run before I compile c code I set ML_ARCH=r8.
I can do check in Makefile as below:
ifeq ($(ML_ARCH), r8)
endif
But for C code how to compare variable against string which is mix of char and number, in preprocessor #if

how to compare in #if condition of preprocessor for string
It is not possible to compare strings in preprocessor.
You can add something unique to r8 to make it longer and define it to a number. You could just #define r8 1, but r8 is a bit short and could be break random code.
// #define ML_ARCH r8
#define ARCH_r8 1
#define ARCH_some_other_arch 2
#define ARCH_etc 3
#define XADD_ARCH(a) ARCH_##a
#define ADD_ARCH(a) XADD_ARCH(a)
#define IS_ARCH(a) (ADD_ARCH(ML_ARCH) == ARCH_##a)
// #if XCONCAT(ARCH_, ML_ARCH) == ARCH_r8
#if IS_ARCH(r8)
Overall, consider doing -D ML_ARCH=ARCH_r8 and then just #if ML_ARCH == ARCH_r8.

Related

Can C-preprocessor can output as a string the evaluation of compiled known constants values(e.g. 150000UL/1000UL)? #define arithmetics

I'm wondering if it can be written that the prepocessor evaluates assigned constants known at compile time and returns the result as a string. I believe the answer is no or complex, but I'll give a try.
Basically I have constants which are expressed in milliseconds but I want to display the results as secs, therefore divide by 1000, and wonder because all is known at compile time, if the preprocessor can directly put the result of this division into the code rather than eval at runtime.
Example:
#define FREQ_AUTO_WHEN_RELAY_ON 150000UL
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
STR( FREQ_AUTO_WHEN_RELAY_ON/1000UL ) " secs"
would yield to "150000UL/1000UL secs"
which is not I want to display, aka "150 secs"
Thanks
You have to first prepare a header with all possible outputs:
// calculate.h
#if VALUE == 1
#define RESULT 1
#elif VALUE == 2
#define RESULT 2
/* etc. millions of lines */
#elif VALUE == 150
#define RESULT 150
#endif
Then you can do:
#define VALUE FREQ_AUTO_WHEN_RELAY_ON/1000UL
#include "calculate.h"
STR(VALUE)
Similarly, you first have to define a matrix of all possible combinations of values:
#define DIV_1UL_1UL 1
#define DIV_1UL_2UL 0
#define DIV_2UL_1UL 2
/* etc. really millions of lines */
#define DIV_150000UL_1000UL 150
Then you can:
#define DIV(a, b) DIV_##a##_##b
#define XDIV(a, b) DIV(a, b)
STR(XDIV(FREQ_AUTO_WHEN_RELAY_ON, 1000UL))
Can C-preprocessor can output as a string the evaluation of compiled known constants values(e.g. 150000UL/1000UL)?
Yes, but it's not practical. Instead, generate the header file from a build system.

How do I concatenate two string macros in C?

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
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.
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

A question regarding #if defined (macro name)

#if defined(_WIN32)
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
So the above is the first 4 lines of C language code from a file of some project.
I do know that #if defined (macro name) means that if the macro is defined, the value of the expression is 1 and if not, then it's 0.
So basically, the first two lines will be either 1 or 0 but what would they do? 1 or 0 just sitting alone?
It's defined() which will be evaluated to either 0 or 1 and from that value if will decide if it should go to the body. It's like normal if statement.
So basically, the first two lines will be either 1 or 0 but what would they do? 1 or 0 just sitting alone?
#if expression
won't result in a line replaced by the result of expression but the preprocessor will decide upon the value of expressen in
#if expression
controlled text
#endif /* expression */
if it will process the controlled text or not.
So basically, the first two lines will be either 1 or 0 but what would they do? 1 or 0 just sitting alone?
No, the #if would stay, just the defined() would become 0 or 1.
So assuming for example _WIN32 and _CRT_SECURE_NO_WARNINGS were defined, then the 1st two line you show looked like:
#if 1
#if 0
Those two if-statements control if what is following is taken into account until the next #endif statement.
The above snippet though is incomplete and should look like this:
#if 1
#if 0
#define FOO 42
#endif
#endif
The above would not #define FOO.
The below would not #define FOO as well:
#if 0
#if 1
#define FOO 42
#endif
#endif
The following will define FOO:
#if 1
#if 1
#define FOO 42
#endif
#endif
Back to your example code:
The stuff "controlled" by the outer if-statement
#if defined(_WIN32)
is
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
The stuff "controlled" by the inner if-statement
#if !defined(_CRT_SECURE_NO_WARNINGS)
is
#define _CRT_SECURE_NO_WARNINGS

Is there a way to get the value of __LINE__ on one line and use that value on other lines?

Essentially, I want to do this:
#include "foo.h"
#include "bar.h"
static const unsigned line_after_includes = __LINE__;
int main()
{
foo(line_after_includes);
bar(line_after_includes);
return 0;
}
Except like this:
#include "foo.h"
#include "bar.h"
#define LINE_AFTER_INCLUDES __LINE__
int main()
{
FOO(LINE_AFTER_INCLUDES);
BAR(LINE_AFTER_INCLUDES);
return 0;
}
Is it possible to make LINE_AFTER_INCLUDES expand to the value of __LINE__ on the line on which LINE_AFTER_INCLUDES was defined, so I can use it with other macros later? I would just use a variable like in the first code snippet, but I need the value as an integer literal, because I will be using it in a switch statement. The alternative is to do
#define LINE_AFTER_INCLUDES 3 // MAKE SURE THIS IS ON LINE IT'S DEFINED AS!!!
which is ugly and harder to maintain. I would settle for that, but I will be doing something a bit more complex than this example...
The best way to do this is given in #Bathsheba's answer here: https://stackoverflow.com/a/24551912/1366431
typedef char LINE_AFTER_INCLUDES[__LINE__];
You can then access the value of __LINE__ at that declaration by calling sizeof(LINE_AFTER_INCLUDES), because its value has been fixed into part of the newly-declared array type. sizeof is a C-level compile-time constant, which works for switch and related things (no division is necessary: the size of char is guaranteed to be 1, as it's the unit of measurement). The only disadvantage of this is that it's C-level rather than preprocessor-level, so it can't be used with #if or for token-pasting.
(original, which I spent ages typing:)
So the problem here is that macro definitions are lazy; i.e. that macro invocations aren't expanded until they're actually needed to be inserted into some kind of output. Because of this, __LINE__'s expansion is delayed until it's too late.
Luckily, there's a way to force eager evaluation in the preprocessor - the macro only needs to be demanded by some kind of output - not necessarily program body text. Remember that macros can also be expanded to form the arguments to preprocessor directives - and that preprocessor directives are then - having been controlled by the forced expansion - able to create further definitions. This handy observation is the basis of Boost's "evaluated slots" functionality, which uses it to provide things like eager evaluation and mutable preprocessor variable slots.
Unfortunately you can't use Boost slots with __LINE__, as it suffers from the same problem - but we can steal the idea to produce two rather inelegant solutions. They're each ugly in their own special ways.
Option 1:
Use a shell script to produce a large number (a few hundred?) of include-able files with the following naming scheme and contents:
// linedefs/_42_.h
#define LINE_AFTER_INCLUDES 42
...then use as follows:
#define GEN_LINE_INC(L) _GEN_LINE_S(_GEN_LINE_(L))
#define _GEN_LINE_(L) linedefs/_##L##_.h
#define _GEN_LINE_S(S) _GEN_LINE_S2(S)
#define _GEN_LINE_S2(S) #S
#include "foo.h"
#include "bar.h"
#include GEN_LINE_INC(__LINE__)
int main()
{
FOO(LINE_AFTER_INCLUDES);
BAR(LINE_AFTER_INCLUDES);
return 0;
}
In other words, use the #include directive to force expansion of a macro which converts __LINE__ into a filename; including that filename produces the right value for the constant. This is inelegant because it requires a load of extra files and an external tool to generate them, but it's very simple.
Option 2:
Insert a large and ugly block into your main file below the #include section:
#include "foo.h"
#include "bar.h"
// <- This line is the one we generate the number for
#define LINE_BIT_0 0
#define LINE_BIT_1 0
#define LINE_BIT_2 0
#define LINE_BIT_3 0
#define LINE_BIT_4 0
#define LINE_BIT_5 0
#if (__LINE__ - 7) & 1
# undef LINE_BIT_0
# define LINE_BIT_0 1
#endif
#if (__LINE__ - 11) >> 1 & 1
# undef LINE_BIT_1
# define LINE_BIT_1 (1 << 1)
#endif
#if (__LINE__ - 15) >> 2 & 1
# undef LINE_BIT_2
# define LINE_BIT_2 (1 << 2)
#endif
#if (__LINE__ - 19) >> 3 & 1
# undef LINE_BIT_3
# define LINE_BIT_3 (1 << 3)
#endif
#if (__LINE__ - 23) >> 4 & 1
# undef LINE_BIT_4
# define LINE_BIT_4 (1 << 4)
#endif
#if (__LINE__ - 27) >> 5 & 1
# undef LINE_BIT_5
# define LINE_BIT_5 (1 << 5)
#endif
#define LINE_AFTER_INCLUDES (LINE_BIT_0 | LINE_BIT_1 | LINE_BIT_2 | LINE_BIT_3 | LINE_BIT_4 | LINE_BIT_5)
int main() ...
This version uses the #if directive to force expansion of the __LINE__ macro and convert it into bitflags, which are then recombined at the end. This is highly inelegant because it relies on precomputing the distance between each #if and the top of the block, since __LINE__ evaluates to different values in the course of the block; and it can't be factored out and hidden in a separate file, or else __LINE__ wouldn't work. Still, it works, and it doesn't require an external tool.
(In the event you have a huge number of #include lines, extending it to more than 6 bits should be straightforward.)
On the other hand, this sounds like an X/Y problem to me. There has to be an alternative to __LINE__ that would work better for this. If you're counting the number of #included files, perhaps you could use something like a line incrementing Boost.Counter at the end of each one? That way, you also wouldn't be vulnerable to formatting changes (e.g. blank lines in the #include section).

How to define a constant conditionally

I want to define some constants in my C file.
Its assembly code like this:
Const1 = 0
Const2 = 0
IF Condition1_SUPPORT
Const1 = Const1 or (1 shl 6)
Const2 = Const2 or (1 shl 3)
ENDIF
IF Condition2_SUPPORT
Const1 = Const1 or (1 shl 5)
Const2 = Const2 or (1 shl 2)
ENDIF
Could you tell me the simplest way to implement this?
And it should be flexible enough because the number of both my constants and conditions is over 10.
After seeing the first three answers, I guess I need to explain more;
What I want to know is how to redefine my constant based on its previous value.
You can do so using preprocessing directives:
#if Condition1_SUPPORT
#define Const1 (1 << 6)
// ...
#elif Condition2_SUPPORT
#define Const1 (1 << 5)
// ...
#endif
To address the edit to the question: you can't redefine a macro based on its previous value. A macro can only have one value at a time and its replacement list is only evaluated when it is invoked, not when it is defined. For example, this is not possible:
#define A 10
#define A A + 10
First, it is an illicit redefinition of the macro: when the second line is handled, A is already defined as a macro, and so it cannot be redefined with a different replacement (you have to #undef the macro name first).
Second, were this licit (and many compilers do accept it), the second line, when invoked, would evaluate to A + 10, not 10 + 10 or 20 as you want: by the time the second macro definition could be invoked, the first definition no longer exists.
You can, however, use different names, like so:
#define INITIAL_A 10
#define A INITIAL_A + 10
You should consider getting one of the introductory books from The Definitive C Book Guide and List; any of them would cover what can be accomplished using the preprocessing directives in some detail.
You can't redefine the value of a constant once you assign it -- if you could, it wouldn't be a constant, would it? Since it looks like you're trying to set various bits in a constant based on preprocessor flags, you could #define separate constants for each condition's contribution, then build the final value at the end:
#if Condition1_SUPPORT
# define Const1_Cond1_Bit (1 << 6)
# define Const2_Cond1_Bit (1 << 3)
#else
# define Const1_Cond1_Bit (0)
# define Const2_Cond1_Bit (0)
#endif
#if Condition2_SUPPORT
# define Const1_Cond2_Bit (1 << 5)
# define Const2_Cond2_Bit (1 << 2)
#else
# define Const1_Cond2_Bit (0)
# define Const2_Cond2_Bit (0)
#endif
#define Const1 (Const1_Cond1_Bit | Const1_Cond2_Bit)
#define Const2 (Const2_Cond1_Bit | Const2_Cond2_Bit)
You can then #undef all the intermediate constants, if namespace pollution is a concern.
You can use pre processor macros to conditionally define a constant variable, like
#if SOME_CONDITION
const int my_constant = 10;
#else
const int my_constant = 5;
#endif
In C, you would use preprocessor macros to accomplish that:
#ifdef COND1_SUPPORT
#define CONST1 CONST1_VAL1
#define CONST2 CONST2_VAL1
#elif COND2_SUPPORT
#define CONST1 CONST1_VAL2
#define CONST2 CONST2_VAL2
#endif

Resources