Processing some directives leaving others - c

I use to go through C code having lot of #ifdef, #if and #endif directive which keep some portion active and some portion inactive depending on some variables are defined or not. I searched for something that can process them to generate final C code. But the preprocessing also does the same for #include and #define. But I want to keep them.
So, is there any thing to preprocess these files or project with some filtering?

There are a series of programs that can do that:
unifdef - the oldest
sunifdef (Son of Unifdef)
coan (Son of sunifdef)
I've used sunifdef extensively on some very contorted code and have never found it to make a mistake. I'm ready to start using coan now, though it will still be under scrutiny for a while. Version 4.2.2 was released today, 2010-12-20.
See also: SO 525283

I assume you're using gcc.
If you mean all #includes, I think you need to remove them, expand the resulting file with gcc -E then add the #includess back.
If you mean only the standard headers, the option -nostdinc may help you do what you want
user#host:~/test/tmp$ cat 4437465.c
#include <stdio.h>
#ifndef OUTPUT_TYPE
#define OUTPUT_TYPE 1
#endif
int main(void) {
#if OUTPUT_TYPE == 1
printf("output type 1\n");
#elif OUTPUT_TYPE == 2
printf("output type 2\n");
#else
printf("default output type\n");
#endif
return 0;
}
user#host:~/test/tmp$ gcc -DOUTPUT_TYPE=2 -nostdinc -E 4437465.c
# 1 "4437465.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "4437465.c"
4437465.c:1:19: error: no include path in which to search for stdio.h
int main(void) {
printf("output type 2\n");
return 0;
}

what you want might be actually a bad idea, as there might be definitions coming from included files, describing your architecture, for example... But any modern IDE can visualize the #if preprocessor directives.

We used a custom parser to achieve what you intend to do. Lex & YACC
would be a good start for such tool.
On a side note, it was a really painful way to manage different versions of binaries in a large code base. If it's possible, try to isolate your optionnal code parts in different libraries that can or cannot be included in your final deliverable as a dynamic or static library.

Related

stdint.h include_next'd from stdint.h not found

I have been putting together a m68k cross compile "environment/toolchain" of sorts for some upcoming projects I have planned, and I'm having an issue when using it on macOS (my native environment) specifically.
If I follow my own instructions to install on Linux (https://github.com/tomstorey/m68k_bare_metal/blob/master/INSTALL-Debian-Ubuntu.md), then in my code I am able to use types such as uint8_t etc through #include <stdint.h>.
But if I install on macOS and attempt to do the same thing I am greeted with this error:
In file included from main.c:1:
/Users/tstorey/m68k/m68k-unknown-elf/lib/gcc/m68k-unknown-elf/9.3.0/include/stdint.h:9:16: fatal error: stdint.h: No such file or directory
9 | # include_next <stdint.h>
| ^~~~~~~~~~
compilation terminated.
make: *** [main.o] Error 1
I've done a little searching around, but I'm not having much luck finding an answer, perhaps because I don't really know what to search for other than "stdint.h not found".
One topic I did find suggested that include_next shouldnt really be used, but that same person wouldnt recommended modifying the original stdint.h file to work around it. Presumably since in that case it is including <stdint.h> then this file should be located somewhere "system wise", and gcc should know where to look to find it? But presumably that location doesnt exist.
In the same directory where the the stdint.h file I am trying to include is located there is a stdint-gcc.h file which, if I include this in my code, it will compile fine, no worries.
The original stdint.h file does seem to attempt to include this file, but only if __STDC_HOSTED__ is not defined:
$ cat stdint.h
#ifndef _GCC_WRAP_STDINT_H
#if __STDC_HOSTED__
# if defined __cplusplus && __cplusplus >= 201103L
# undef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
# undef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
# endif
# include_next <stdint.h>
#else
# include "stdint-gcc.h"
#endif
#define _GCC_WRAP_STDINT_H
#endif
Sorry if this post is a bit wofty, but I am not experienced enough with gcc etc to really be able to work this out and I'm still learning a lot about setting all of this up, so I'm wondering if anyone knows what I have missed.
Thanks
When your particular version of gcc has been built, it was apparently not built for a hosted environment (i.e. full availability of a standard C library, for example newlib). When this is the case, you cannot expect standard library support and are on your own.
You probably want to re-build gcc with newlib support.

How to #include a different file each time based on user input?

I have a program which, depending on the user input, #includes one header headerA.h or another headerB.h I expect the header to be there till the end of the program.
headerA and headerB define structures with the same names but with different fields, and I'm not able to merge both files in one, and neither able to change anything else from the libraries that headerA and headerB are using.
Is there a way to solve this problem?
Preprocessor macros:
#if defined(USE_HEADERA)
# include "headerA.h"
#elif defined(USE_HEADERB)
# include "headerB.h"
#else
# error must define USE_HEADERA or USE_HEADERB
#endif
If you have GCC then you tell the preprocessor which to select using the GCC -D option:
$ gcc -DUSE_HEADERA myfile.c -o myprogram
However, if you want to do it runtime during execution that's impossible. #include is a preprocessor directive, and the preprocessor only runs as part of the compilation.
Although it is possible to conditionally include files, it does not seem to be possible to have this change during runtime. See this answer about it. The if statements only work before runtime.
I don't think it is possible as your #includes are resolved before compilation i.e during preprocessing. So it is not possible to change them during runtime.
But you can try conditional compilation by defining a macro during compiletime.
#ifdef HEADERA
#include <headerA>
#ifdef HEADERB
#include <headerA>
While compilinging gcc
$ gcc prog.c -DHEADERA to include headerA or vice versa

#define scope in multiple files

I have a main file like so:
main_a.c:
#define MAIN_A
#include <stdio.h>
#include "shared.h"
extern int i;
int main() {
printf("i is: %d\n", i);
return 0;
}
I want to use the define in shared.h like this:
shared.h
#if defined(MAIN_A)
# define A
#endif
So I can declare a variable according to whether the main file is present or not, like this:
shared.c
#include "shared.h"
#if defined(A)
int i = 1;
#else
int i = 0;
#endif
I build it using a makefile which looks like this:
Makefile:
all : a
./a
a : main_a.o shared.o
gcc -o $# $^
%.o : %.c
gcc -c $<
However this prints
i is: 0
Now my question is: Why is it that the define seems to be lost when I compile the shared module? I know the main module is compiled first, so the define should have been resolved by the time shared.c is compiled.
One suspicion I have is that the preprocessor might get run at the start of each module build and not just at the start of the project. If this is correct is there a way of compiling more than a single module at a time to use the preprocessor as I attempt above?
Preprocessor is run for each file before it is compiled, i.e. once for main_a.c and then again independently for shared.c. When shared.c is compiled MAIN_A is undefined.
Preprocessor can't be used the way you're attempting, i.e. remembering state across compilation units.
What you can do is define a name (for example MAIN_A) using the -Dcompiler option in your Makefile and test this name using preprocessor the same way you're doing it now. This way the definition takes place on the project level (in the Makefile) rather than on a compilation unit level (in a .c file).
Let me do the preprocessor's work here and expand all your macros. In main.c, MAIN_A is defined, so A is defined. Nothing depends on A in main.c, and i is extern.
In shared.c, MAIN_A and thereby A are undefined, and i is 0.
In short, the preprocessor cannot transport information between compilation units. That's good practice, because otherwise programs would quickly become unreadable and you would have to recompile all compilation units when one unit changes (because symbols might have changed). Resolve the issue by setting i explicitly in main:
int main() {
i = 1;
}
It is more verbose, but is also much clearer to the reader. If you want to encapsulate, define a function InitializeShared. If you truly want to compile some code as a single compilation unit, make one of the files a header file and #include it into the other.
Yes you are right, they are completely separate compilation units.
MAIN_A is only defined in main_a.c
One thought that comes to mind is to cat the files together to make one compilation unit?
Global define A
gcc main_a.c shared.c -DA
Defines almost work the same as any variable. If you want to share a variable across modules, you put it in a header. Same goes for #defines.
However, it is strange to use the #ifdef as you are always going to have main.c. You don't want to change the code each time you compile. Instead, use the method described by Adam Zalcman

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.

Make the C preprocessor ignore certain #include directives

I use a parser generator here, that unfortunately insists on putting a
#include <some/file.h>
at the top of every generated source file. The header has since long been renamed. While it is no problem forcing the compiler (gcc) to use the new header with -include new/header.h, removing the above directive from every generated file complicates the build-process.
Is there a way to tell gcc to simply ignore some/file.h?
No. You can post-process your generated file - I say: NO!!!
Or you can just add '.' to your system include directories (or whatever your local include path is - make sure it's also a <> system include path).
Then make a 'some' directory and stick your own permanent 'file.h' in there that has 1 line for #include and get rid of your -include.
I'm guess there's some reason that might not work - cause it seems like the more straight forward and understandable thing to do before using -include. Especially since you can comment the pass-through file to explain what's going on.
Replace some/file.h with an empty file.
Why not make a symlink from some/file.h to new/header.h, and remove the -include directive?
Try using preprocessor directives like #if and #ifdef and gcc -DSYMBOL=value command line flag.
In example, if you compile using gcc -DREQUIRE_STDC=1 -o myfile.o myfile.c, and your .c file contains:
#if defined(REQUIRE_STDC) && defined(__STDC__)
#include "some/file.h"
#else
#include "another/file.h"
#endif /* defined(REQUIRE_STDC) && defined(__STDC__) */
It will compile using "some/file.h" if have both STDC and REQUIRE_STDC symbols defined. Also your header may include the proper directive to avoid multiple inclusions of the same file:
#ifndef MY_HEADER_FILE
#define MY_HEADER_FILE 1
/* your C declarations here */
#endif /* MY_HEADER_FILE */
Also, you could the gcc preprocessor manual.
#include <some/file.h>
may start as something like
#ifndef _FILE_H_
#define _FILE_H_
If so, just add #define _FILE_H_ before the #include command and it should ignore it.
I'm not sure whether this is the best solution, though.

Resources