Reputation: 164
I was trying to build a C project which has a rather unfamiliar way to define namespaces, eg. in file root.h
#define eval CRYPTO_NAMESPACE(eval)
And in the Makefile the following appears (rule for make all):
gcc -O3 -g -march=native -mtune=native -Wall -I. -Isubroutines -DKAT -DKATNUM='cat KATNUM' "-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x" -o kat nist/kat_kem.c nist/rng.c benes.c bm.c controlbits.c decrypt.c encrypt.c gf.c operations.c pk_gen.c root.c sk_gen.c synd.c transpose.c util.c -I${PWD}/subroutines -L${PWD}/libs/ -lXKCP -lcrypto -ldl
What do these options do:
"-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x"
I know that -DXXX=YYY
is the same as #define XXX YYY
. Now, why is it in double-quotes? Why it looks like a macro (may be it is)? Lastly, what does _##x
mean?
Upvotes: 0
Views: 106
Reputation: 46960
The macro in the header:
#define eval CRYPTO_NAMESPACE(eval)
Replaces every token eval
with CRYPTO_NAMESPACE(eval)
. So if the code contains
void eval(char *expr) {
...
the preprocessor output - without any other definition - would be
void CRYPTO_NAMESPACE(eval)(char *expr) {
...
The -D
parameters effectively add two more definitions:
#define DCRYPTO_NAMESPACE(x) x
#define _CRYPTO_NAMESPACE(x) _##x
In our example, the first define
causes the normal result to be re-written one more time:
void eval(char *expr) {
...
so we're back where we started. A different definition could be used to change the compiled name of the function. This definition makes the header definition a no-op.
The second macro uses the token concatenation operator ##
. It adds a prefix underscore _
to the macro argument. E.g. if the code contained something like:
void _CRYPTO_NAMESPACE(foo)(int x) {
then the result is
void _foo(int x) {
At a higher level, these macros allow names of things (in the first case anything named eval
and in the second, any name at all) to be transformed uniformly throughout the program. This is a fairly standard workaround for name collisions in big C programs. If you have two source code bases that have both defined the same public function name, macros like this can be used to add a prefix or suffix that changes one or both names in the compiled code without modifying either original code. This is an important capability for long-term configuration management where manually editing externally furnished code bases isn't a serious option.
A wild guess is that this treatment is given to eval
because the likelihood of some other chunk of C also defining a function named eval
is extremely high.
Upvotes: 1