gcc check if file is main (#if __BASE_FILE__ == __FILE__) - c

In ruby there's very common idiom to check if current file is "main" file:
if __FILE__ == $0
# do something here (usually run unit tests)
end
I'd like to do something similar in C after reading gcc documentation I've figured that it should work like this:
#if __FILE__ == __BASE_FILE__
// Do stuff
#endif
the only problem is after I try this:
$ gcc src/bitmap_index.c -std=c99 -lm && ./a.out
src/bitmap_index.c:173:1: error: token ""src/bitmap_index.c"" is not valid in preprocessor expressions
Am I using #if wrong?
As summary for future guests:
You cannot compare string using #if
BASE_FILE is the name of file that is being compiled (that Is actually what I wanted).
Best way to do this is to set flag during compilation with -D

in gcc you can use:
#if __INCLUDE_LEVEL__ == 0
or:
if(!__INCLUDE_LEVEL__)
to check if your inside the __BASE_FILE__

Yes, you are misusing #if. It only works on integer constant expressions. But even if you were using if, comparing pointers for equality is never a valid way to compare strings in C.

It seems you can't.
Alternatively, it works perfectly fine on a regular if condition, and gcc can optimize this nicely.
if (!strcmp(__BASE_FILE__, __FILE__)) {
// works.
}
but you can't define new main functions or use other preprocessor tricks. but you could short-circuit main by using static methods, but that's harsh and dirty.
But maybe you shouldn't do it. in Ruby/python, this works because usage of files is done at runtime. in C, all files are to be compiled to be used.
Keep in mind that most build system will build one file at a time, building them as object files, and rebuilding them only when necessary. So
__BASE_FILE__ and __FILE__
will be equals most of the time in sources files, if not always. And i would strongly discourage you to do this in header files.
It's easier to just put your tests in separate files, only linking them when needed.

Yup, as others say, you're misusing it since you can't compare strings that way in C, and especially not in the preprocessor.
The file that defines int main(int argc, char* argv[]) is the main file. There can be only one such function in an executable.

In addition to what others have said (you can't have the C preprocessor compare strings), be careful with __BASE_FILE__ because it may not correspond to your definition of "main" file. __BASE_FILE__ is the name of the file being compiled, so it's always equal to __FILE__ in source files, and only differs in headers and other included files.
In particular, __BASE_FILE__ is not the name of the file which contains the main() function.

Related

C Makefile commands

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

is it possible to use the preprocessor __file__ to generate a #define in C?

In order to improve the aesthetics of some code, I would like to have a .h file contain some code that sets a #define based on which file the .h file is included from. For example
#if (__file__ == "main.c")
#define MOUDLE MODULE_MAIN
#elif (__file__ == "foo.c")
#define MODULE MODULE_FOO
#endif
Is there any way to accomplish something like this? The main motivation is to avoid putting a #define MODULE at the top of every file and instead have one location where the mapping is defined and to just include the same .h file.
No, you can't do this. #if can only do integer expressions. It knows nothing about strings or how to compare them.
What you want is not possible with the standard C preprocessor. Check by reading the C standard, eg n1570, or some C reference, or the wikipage on the C preprocessor, or the GNU cpp manual.
But consider another way to achieve the same: configure appropriately your build automation.
For example, if you use make, then edit your Makefile appropriately. How to do that is a very different question.
You could have a rule for make which passes a specific -DMODULE=name to gcc
For example in my bismon (on github) the Makefile has near line 141 something similar to
modules/modbm_%.so: modules/modbm_%.c bismon.h $(GENERATED_HEADERS) $(BM_HEADERS)
$(CCACHE) $(LINK.c) -fPIC \
-DBISMON_MODID=$(patsubst modules/modbm_%.c,_%,$<) -shared $< -o $#
Be creative. The build machinery is part of your source code. Adapt it to do what you want. Don't expect the standard preprocessor to cover all your needs. Learn how to invoke GCC (or your favorite compiler) on the command line. In some cases, it is even worthwhile to generate some C file (perhaps some header file), and you might use another preprocessor (like GPP or m4) for that purpose.
Remember that the compiler (notably GCC and Clang) is a command line program, that you should drive from something else (like make, ninja or many other build automation tools).
(even on microsoft systems the compiler is still a command line thing, but that fact is often ignored)
BTW, I dislike many IDEs because they are hiding the build process, and you need to master it. So you need to configure it (e.g. by writing your Makefile or something else) and to understand and tailor it.
The main motivation is to avoid putting a #define MODULE at the top of every file and instead have one location where the mapping is defined
That single location defining such a mapping should probably be your build infrastructure (e.g. your Makefile if using make); you'll adapt it to invoke gcc or clang (or most other C compilers) with an appropriate -DMODULE=name flag. (BTW, you also want the convention that your base name of sources files are C identifiers, so you won't have any a-1.c file -since a-1 is not an identifier-, but a bcde.c one).
If using GNU make, read its documentation, then run make -p to understand the rules (both builtin, and custom) relevant to your case. Then consider perhaps a rule similar to:
%.o: %.c $(YOURHEADERS)
$(COMPILE.c) -DMODULE=$(patsubst %.c,MODULE_%,$^) -c $< -o $#
but adapt that rule to your needs. (you could need some $(shell ... ) inside it if your file names are lower cases, and you want upper case MODULE).
BTW, you could also generate parts of your Makefile (or have some generated C files, which you would #include appropriately).

How to invoke the C preprocessor?

How can we invoke the C preprocessor in a C program, like if we want to prepend some of our files to the list of standard library files while using #include<file_name> using -I, what we should do?
Adding, if we want to add comments to the output of our program, I have heard that we can use -C invocation commands. How to do it? Somebody please correct me and explain further if I am wrong.
The mechanism you linked to is explicitly not to be supposed from within a program, but it is to use the preprocessor for other things, like text libraries etc.
So you can transform a text using the means of the C preprocessor and convert it to its "expanded" form, without compiling it (perhaps it is a configuration file or whatever).
For example, you can have a
commonpart.h:
[General]
foo=1
bar=2
#define VALUE 3
and a
cfg.tmpl
#include "commonpart.h"
// This is a commet which won't show up in the end
baz=VALUE
you can do cpp -P cfg.tmpl and thus compile all this to
[General]
foo=1
bar=2
baz=3

Environment variabile in Macro path

I need to define some path to files with macros. How can I use the $HOME environment variable?
I can't find it on the GNU manual, and this doesn't work:
#define LOGMMBOXMAN "$HOME/mmbox/LOGmmboxman"
No it shouldn't and you probably don't want constant-defined settings like that in any case. If you did that and it worked as you're intending to use it, your home directory would be built in as whatever $HOME is for whoever's doing the building. The executable then depends on that specific home directory existing. If that's OK, just #define your own home. I suspect it isn't though, so you need to deduce it at runtime.
For run-time deduction what you want is this, such that:
const char* home_dir = getenv("HOME");
If there is no $HOME defined, you get NULL returned so be sure to test for this.
You can then build your string based on that. You'll need #include <stdlib.h>.
Sounds like you are really asking "how can I set some cpp macro from my environment?"
If sothen you should just be able to add it to CPPFLAGS.
export CPPFLAGS="$CPPFLAGS -D LOGMMBOXMAN=$HOME/mmbox/LOGmmboxman"
Then in your code
#ifndef LOGBOXMAN
#error LOGBOXMAN not defined
#endif
Then make sure your source is built using the CPPFLAGS in the command line to gcc:
$ gcc -c file.c $CPPFLAGS
You can't. You need to use your build system to define a macro with the $HOME value (or equivalent on a non-unix system), i.e. something like this:
gcc -DHOME="/home/username" file.c
Or "/Users/username" for Mac OS X, or "C:\Users\username" (or something) for Windows. Basically, GCC provides the -D flag to define a macro on the command line. You can set up a script (or your build system) to take care of this macro definition for you, or perhaps make a system-dependent include file to define the HOME macro properly.
Then, in your C header, you can do:
#define LOGMMBOXMAN HOME "/mmbox/LOGmmboxman"
Note that, in C, consecutive string literals are concatenated. So this macro expands to:
"/home/username" "/mmbox/LOGmmboxman"
Which C interprets as
"/home/username/mmbox/LOGmmboxman"
EDIT: All that thinking, and I didn't think! D'oh!
As others have pointed out, you probably don't want to do this. This will hard-code your program to work for one specific user's home directory. This will likely cause problems if you want each user to use your program, but for each to keep his (or her) own separate files.
Ninefingers' answer is what you're most likely looking for. In the event that you ever find yourself in need of the above technique (i.e. storing application files in a system-specific place) I will leave my answer unchanged, but I expect it won't help you here.

Pre-preprocessor

I want to have a C pre-preprocessor which is filtering some #define statements from the sourcecode without changing anything else.
Why? This should be used to remove some client specific code from the sources if the source is handed out to another client.
Does anyone know of an existing solution?
Thanks!
Simon
You can use something like awk instead of CPP ? Add some flags in your code surrounding the piece of code to be removed. For example:
(...)
//BEGIN_REMOVE_THIS_CODE
printf("secret code");
//END_REMOVE_THIS_CODE
(...)
then write a awk script to remove this code, something like...
BEGIN { write=1;}
/^\/\/BEGIN_REMOVE_THIS_CODE/ { write=0; next;}
/^\/\/END_REMOVE_THIS_CODE/ { write=1; next;}
{
if(write==1) print $0;
}
I recommend using an additional macro language layer for code filtering, like filepp. You may use a C preprocessor friendly syntax to express which parts belongs to which clients.
//%ifdef CLIENT_A
code for client A
//%endif
//%ifdef CLIENT_B
code for client B
//%endif
//%if "CLIENT_A" || "CLIENT_B"
code for client A and B
//%endif
The '//%' prefix enables You to compile the code unmodified. You may run filepp before You giving out the code to a client.
This sounds like what I asked about in Is there a C pre-processor which eliminates ifdef blocks based on values defined. The best answer I got was sunifdef, or 'Son of unifdef', which has worked reliably for me on some excessively contorted conditional code (the accumulated crud from over 20 years of development on a wide variety of platforms with an inadequate theory of how to do platform-specific compilation).
I don't think you need a preprocessor for this. If you don't have nested #ifdef's in your code, any regex engine can remove anything that is located between #ifdef CLIENT and #endif (use non-greedy matching to match first #endif, not last).
I would put the client specific code in a separate directory or possibly part of a different project that would need to be checked out of the source control.
Put a function call that would be stubbed out or (I forget the proper term) loosely linked so that another function can be put in its place.
If you're using gcc, then you can use:
gcc <insert files here> -E
The -E option tells gcc to only preprocess the sources, and not to compile them.
Or, you could use grep to filter out specific files and let the preprocessor loose on them only.
grep -r '#define CLIENT_CODE' ./*.h
You can also try unifdef which is rather simpler than sunifdef.
Why don't you do something like:
client_a_specific_functions_definition.c
double discount_for_paying_upfront() { return 0.1; };
// ...
client_b_specific_functions_definition.c
double discount_for_paying_upfront() { return 0.05; };
// ...
When you hand out the code it is just a matter of selecting the right file with their specific definitions.
Then you would create a header file to include it where you need to access the client specific code with something like:
client_functions.h
#pragma once
double discount_for_paying_upfront();
#define stringify(x) #x
#define FILE2(a) stringify(client_##a##_specific_functions_definition.c)
#define FILE(a) FILE2(a)
#include FILE(CLIENT_NAME)
#undef stringify
#undef FILE2
#undef FILE
Then say you #include "client_functions.h" in your main.c. You could compile it with:
gcc -DCLIENT_NAME=a main.c -o a.exe
gcc -DCLIENT_NAME=b main.c -o b.exe
as far as I know... the preprocessor can be run as a separate step (using the correct compiler optios) . This way you can do whatever you want with the processed code.

Resources