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

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.

Related

C preprocessor macro

The problem:
I'm writing a general C library for an LCD in a microcontroller project.
up to 8 LCDs with various sizes(e.g. 128*96 or 64*48) in various addresses may be added (e.g. LCD3 and LCD7). but only one of them is actively coded at a time. so I thought for a mechanism to do so.
in the code, there is a definition for CLCD_ROWS and CLCD_COLS which correspond to the Active display size.
#define CLCD_ROWS // Active LCD rows
#define CLCD_COLS // Active LCD columns
and there's definitions for the various LCDs. for example, if we have LCD3 and LCD7 connected, we define their sizes with :
#define CLCD_ROWS3 96
#define CLCD_COLS3 64
#define CLCD_ROWS7 128
#define CLCD_COLS7 32
The question:
I've written a [wrong] macro to redefine the values of CLCD_ROWS and CLCD_COLS :
#define cLcd_setActiveI2CcLcd(X) \
CLCD_ROWS = CLCD_ROWS##X \
CLCD_COLS = CLCD_COLS##X
and in my main code I call the macro:
cLcd_setActiveI2CcLcd(7);
which gives me an error of "missing ;".
it is easy to implement it with variables. but since these values are hardcoded , I thought they are "preprocessable" since need every bit of RAM in a low end MCU.
Is my approach about preprocessing this values, correct ?
What is the right way to write a macro for that purpose ?
I'm using a C99 compiler.
First things first, your method of using function-type macro is wrong. Even if you fix the error you have, the macro will not do CLCD_ROWS equal to CLCD_ROWS7, but to CLCD_ROWSX (that is how macros work, it concatenates the thing you give, not its value). Instead if you want to use macros for reducing RAM usage you can change your code to:
1st Solution
#define ROW_COLS 7 // change this if you use different display
#if ROW_COLS == 7
#define CLCD_ROWS 128
#define CLCD_COLS 32
#elif ROW_COLS == 3
#define CLCD_ROWS 96
#define CLCD_COLS 64
#endif
2nd Solution
If you want dynamically change the size of your display in the runtime, you can do it like this:
static int display_cnt;
#define CLCD_ROWS ((display_cnt == 3) ? 96 : 128)
#define CLCD_COLS ((display_cnt == 3) ? 64 : 32)
So when you change the value of display_cnt variable, the macro will automatically change its value.

Can I decrement a define value at each repeat of itself at compile time?

Such as this:
#define ERROR_CODE_A -1
#define ERROR_CODE_B -2
#define ERROR_CODE_C -3
but this way:
#define ERROR_CODE_A DEFINE_TRICK(start_value)
#define ERROR_CODE_B DEFINE_TRICK(start_value)
#define ERROR_CODE_C DEFINE_TRICK(start_value)
where start_value may be some define trick so that multiple usage of it decreases itself.
I couldn't find anything but it can help in a situation where there will be hundreds of error codes and adding a new error code between two breaks continuous value mapping such as
#define ERROR_CODE_XY -1234
#define ERROR_CODE_XZ -1235
#define ERROR_CODE_NEW -3455 <---- how can I make this derived automatically?
#define ERROR_CODE_ZW -1236 <---- so that this and all following are changed

Preprocessor: missing binary operator before token

I'm trying to set up the USART module in an XMEGA micro controller and stumble over an error I can not find. For clarity I give you the complete code. So nothing in this header file is missing. (F_CPU is defined in the main file)
#ifndef USART_H_
#define USART_H_
#include <avr/io.h>
#define USART_BAUDRATE 4800
#define USART_BSCALE -3
#if USART_BSCALE < 0
#define USART_BSEL F_CPU / (pow(2,USART_BSCALE) * 16 * USART_BAUDRATE) - 1
#define USART_BAUD_REAL F_CPU / (pow(2,USART_BSCALE) * 16 * (USART_BSEL + 1))
#else
#define USART_BSEL (1 / (pow(2,USART_BSCALE))) * (F_CPU / (16 * USART_BAUDRATE) - 1)
#define USART_BAUD_REAL F_CPU / (16 * ((pow(2,USART_BSCALE) * USART_BSEL) + 1))
#endif
#define USART_BAUD_ERROR USART_BAUD_REAL * 1000 / USART_BAUDRATE
#if USART_BAUD_ERROR<990 || USART_BAUD_ERROR>1010 /* <-- ERROR IS IN THIS LINE! */
#error Baud rate error too high!
#endif
#endif /* USART_H_ */
The compiler ends with the error
missing binary operator before token "("
in the marked line. There have been brackets before, but I removed them, tried different bracket combinations but the compiler still does see them there. What is wrong here?
The #if pre-processor directive is evaluated during the pre-processing stages. The function pow is evaluated in run-time. Therefore you can't use it inside pre-processor tokens (macros) that are passed to #if. You'll want to compute all these values at compile-time.
Hint: "2 times n" is the same as 1 << n (bit-wise left shift).
In addition, there are some other serious issues:
You have tagged this AVR so you probably shouldn't use floating point numbers. They will not only make your program incredibly slow and open up for all kinds of bug possibilities, there is nothing gained from using them.
If you are lucky, you would get warnings for "missing floating point library" or similar. If you are unlucky, the program will link and blow away all your execution speed and memory.
It might be wise to check if your target system even has a FPU before considering using floating point.
You need to write macros proper, with parenthesis surrounding the macro expression. Just like your second USART_BSEL which is properly written. Otherwise if your macro is used in an expression, you can get very subtle and very severe bugs related to operator precedence. Every half-decent C book addresses this very issue in the pre-processor chapter.
If you want preprocessor to evaluate an expression, it has to be constant. pow() is a runtime function, it can't be evaluated by the preprocessor at compile time.
Use parentheses around macro bodies, otherwise you'll run into problems.
Watch the type of the number constants. The operations are evaluated according to the types. 1/ANY_NUMBER gives 0, because the division is performed in signed int.
#define USART_BAUDRATE 4800U
#define USART_BSCALE (-3)
#if USART_BSCALE < 0
#define USART_BSEL (F_CPU*(1UL<<(-USART_BSCALE)) / (16U*USART_BAUDRATE) - 1U)
#define USART_BAUD_REAL (F_CPU*(1UL<<(-USART_BSCALE)) / (16U*(USART_BSEL+1U)) )
#else
#define USART_BSEL (F_CPU / ((1UL<<USART_BSCALE)*(16U*USART_BAUDRATE-1U)) )
#define USART_BAUD_REAL (F_CPU / (16U*((1UL<<USART_BSCALE)*USART_BSEL+1U) )
#endif
#define USART_BAUD_ERROR ( USART_BAUD_REAL * 1000U / USART_BAUDRATE )
Suggestion: you can achieve better accuracy for divisions with the rounding trick:
#define USART_BSEL_DIVISOR ((1UL<<USART_BSCALE)*(16U*USART_BAUDRATE-1U))
#define USART_BSEL ( (F_CPU+USART_BSEL_DIVISOR/2) / USART_BSEL_DIVISOR )

C Preprocessor: Stringify int with leading zeros?

I've seen this topic which describes the "stringify" operation by doing:
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)
Is it possible to stringify with leading zeros? Let's say my MAJOR_REV needs to be two characters "02" in this case and MINOR_REV 4 characters "0006"
If I do:
#define MAJOR_VER 02
#define MINOR_VER 0006
The values will be treated as octal elsewhere in the application, which I don't want.
No clean nor handy way to do it. Just as a challenge, here a possible "solution":
1) create a header file (e.g. "smartver.h") containing:
#undef SMARTVER_HELPER_
#undef RESVER
#if VER < 10
#define SMARTVER_HELPER_(x) 000 ## x
#elif VER < 100
#define SMARTVER_HELPER_(x) 00 ## x
#elif VER < 1000
#define SMARTVER_HELPER_(x) 0 ## x
#else
#define SMARTVER_HELPER_(x) x
#endif
#define RESVER(x) SMARTVER_HELPER_(x)
2) In your source code, wherever you need a version number with leading zeroes:
#undef VER
#define VER ...your version number...
#include "smartver.h"
at this point, the expression RESVER(VER) is expanded as a four-digit sequence of character, and the expression STR(RESVER(VER)) is the equivalent string (NOTE: I have used the STR macro you posted in you answer).
The previous code matches the case of minor version in your example,it's trivial to modify it to match the "major version" case. But in truth I would use a simple external tool to produce the required strings.
I believe in the example provided by the question sprintf is the correct answer.
That said, there are a few instances where you really want to do this and with C preprocessor if there is a will and somebody stupid enough to write the code there is typically a way.
I wrote the macro FORMAT_3_ZERO(a) which creates a three digit zero padded number using brute force. It is in the file preprocessor_format_zero.h found at https://gist.github.com/lod/cd4c710053e0aeb67281158bfe85aeef as it is too large and ugly to inline.
Example usage
#include "preprocessor_format_zero.h"
#define CONCAT_(a,b) a#b
#define CONCAT(a,b) CONCAT_(a,b)
#define CUSTOM_PACK(a) cp_ ## a __attribute__( \
(section(CONCAT(".cpack.", FORMAT_3_ZERO(a))), \
aligned(1), used))
const int CUSTOM_PACK(23);

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

Resources