Expanding macros in C according to specified header files - c

I have a source file foo.c and a header file bar.h. How can I just expand the macros in bar.h without expanding macros in other header files?
$ cat foo.c
#include <stdio.h>
#include "bar.h"
int main()
{
#ifdef BAR_FUNC
printf("bar func\n");
#else
printf("foo func\n");
#endif
return 0;
}
$ cat bar.h
#define BAR_FUNC 1
What I want is:
$ EXPAND_MAGIC foo.c
#include <stdio.h>
int main()
{
printf("bar func\n");
return 0;
}
If I use `gcc -E, it expands <stdio.h> as well. But I just want to expand macros in bar.h. Is there an option in gcc doing that? If not, are there any other tools that can do such preprocessing?
Update: Above foo.c/bar.h is just an example. In reality, I have a few hundreds of macros defined in bar.h (pls consider config.h generated by autoconf in a fairly large project). And what I want is to expand all (and ONLY) these macros in more than 10K source files. Any suggestions?

You might look into the program sunifdef which is mentioned in the answer to this question. It allows you specify macro definitions on the command line, and it eliminates #ifdef lines appropriately. Note that it doesn't do macro expansion.
That said, you shouldn't use a tool like this for general development, but it's quite useful for decoding or cleaning up a code that has gotten messy with many unused #ifdefs's over the years.

Unfortunately for you the proeprocessos is all-or-nothing. Either you run it and it includes all requested files and expands all macros.
However you can kind of work around it by using the conditional compilation features of the preprocessor:
#ifndef INCLUDE_ONLY_BAR
# include <stdio.h>
#endif
#include "bar.h"
int main()
{
#ifdef BAR_FUNC
printf("bar func\n");
#else
printf("foo func\n");
#endif
return 0;
}
You can "compile" it as such:
$ gcc -E -DINCLUDE_ONLY_BAR foo.c

You can use an IDE like eclipse. It disables the part of the code which is not compiled. You might not be able to see 'exactly' what you want to see, but you can see a clear difference between disabled code and normal code. Please ignore this option if you don't have luxury of using GUI.
Eclipse also helps in expanding macros which can be very handy when you have complex macros.

Try:
Normally compile: gcc -include stdio.h -imacros bar.h foo.c
Compile to expand ONLY MACROS in bar.h: gcc -E -imacros bar.h foo.c

Related

Include C file which is located in the same folder as the main c file

I have a folder which contains 3 files:
main.c
file1.c
file2.c
The idea is to compile only one file basing on a symbol if it's defined or not.
in main.c, I added the following lines:
#ifdef MY_SYMBOL
#include "file1.c"
#else
#include "file2.c"
#endif
The problem that I found is that when MY_SYMBOL is defined, file1.c is compiled twice because in the makefile it's mentionned to compile all source files inside each folder.
The limitation is that I shouldn't modify the makefile! So, to avoid that I modified the extension of file1.c and file2.c to file1.h and file2.h respectively, by keeping their content (definition of all private functions), and I updated the content of main.c as following:
#ifdef MY_SYMBOL
#include "file1.h"
#else
#include "file2.h"
#endif
Taking into account the above limitation, is the last proposal the best way ?
Note that file1.c and file2.c contain the same functions but with different implementation.
Among others, C programers usually do not expect one of the following:
.h-files that contain function implementations or variable definitions
.c-files that get included.
So I'd say with both ways you will somehow "surprise" others.
If you must not alter the makefile (BTW: why?), you could encapsulate the implementation variants in your .c-files within preprocessor-directives:
// file1.c (OR: file_mysym_implementation.c):
#ifdef MY_SYMBOL
// code goes here
#endif
// file2.c (OR: file_non_mysym_implementation.c):
#ifndef MY_SYMBOL
// code goes here
#endif
Additionally, you will need one header file which declares all the functions exposed by the respective implementation.

How to remap a c header file

I am troubling myself with the following.
I have a file foo.c
that includes foo.h and does some stuff.
The tricky thing is this one. I would like to remap foo.h to my_foo.h. So when the compiler sees foo.h it should go to my_foo.h.
One thing that could work is to include my_foo.h to foo.h. Any other suggestions?
No I cannot include in foo.c my_foo.h
Thank you all in advance
Alter the include path to use a directory controlled by you before it uses the directory holding "foo.h"
In the directory controlled by you make a symlink called "foo.h" which points to "my_foo.h" as the target
Depending on which system you work, you might have no symlinks.
But maybe you can create a foo.h with the following content:
#include "my_foo.h"
What an interesting issue. I'd love to know what you're doing with it.
So if you have control over foo.h, here's a variation on a trick that is used when sharing header files between kernel code and user code in the Linux kernel.
/* File: foo.h */
#ifdef USE_MY_FOO_H
#include <my_foo.h>
#else
#define OVERRIDABLE_FOO_MACRO do { stuff() } while(0)
int overridable_foo_func();
#endif
int not_overridable_foo_func();
Then in your Makefile
/* File: Makefile */
default: foo.c foo.h
$(CC) foo.c -o foo
use_my_foo_h: foo.c foo.h my_foo.h
$(CC) -DUSE_MY_FOO_H foo.c -o foo
BTW, this is not really a great way to form your Makefile, it just demonstrates the compiler commands you can use to switch between the two foo.h files.

sizeof returns different values for the same struct

I have two applications written in C that include the same header. In this header I have the declaration of a struct. I use the GCC compiler to compile both applications.
When I execute both applications, they produce different values of sizeof(struct-defined-in-the-header).
Why does this happen?
First of all, make sure to do a clean build of everything.
If the problem persists, this could mean that different compilation options have been used for the two translation units. I would capture the gcc command lines used for the two compilations, and would compare them, paying particular attention to any options having to do with alignment, structure padding etc.
Another possibility is that the definition of the struct depends on some preprocessor symbols, and the symbols get defined differently for the two translation units. Using gcc -E and comparing the struct definition in the two preprocessor outputs would be a good start.
In my case it wasn't gcc and it was single application, but there were different results of sizeof(MyStruct) in different .c files.
The reason was in different packing values for structures, because those .c files had included different sets of .h files before including header with declaration of MyStruct.
The solution I adopted was to create general header with setting appropriate packing value and including it into all my .h files after system and library headers, but before my headers.
sizeof is not a function. It is a compile-time operator.
You don't tell what header is giving you trouble.
A possible guess might be that some obscure preprocessor trick is removing some field in it, or changing the real type of the field. For example, imagine that one header foo.h has
// in file foo.h
#ifdef FOO_BAR
typedef short number_t;
#else
typedef long number_t;
#endif
and another header bar.h has
// in file bar.h
#define FOO_BAR
#include "foo.h"
struct barbare_st {
number_t num;
char name[20];
};
To find out, you could use the ptype command of the gdb debugger, or simply look into the preprocessed form xxx.i of some file xxx.c obtained with
gcc -C -E -Dappropriate_defines -Iinclude_dirs/ xxx.c > xxx.i
I use Eclipse to compile the programs. I checked flags of compilation. Look:
gcc -I/lib-header-directory-with-struct -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"program-a.d" -MT"program-a.d" -o"program-a.o" "../program-a.c"
gcc -I/lib-header-directory-with-struct -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"program-b.d" -MT"program-b.d" -o"program-b.o" "../program-b.c"
gcc -L/lib-directory-with-struct -o"program-b" -l<lib-with-struct>
The difference between them is that in one I used the lib and in another I used struct definition only.
I used gcc -E and redirect stdout to file. I looked for struct definition in this file and it is the same in both programs.
As Doc Brown commented, there are several possibilities. You should show the code. Here's another guess, though.
Maybe another variable is shadowing your struct in one of the cases? Like in:
extern struct { char foo; } bar;
void baz(void) {
long bar;
sizeof bar; /* will be sizeof(long) */
}
void qux(short bar) {
sizeof bar; /* will be sizeof(short) */
}

unistd.h and c99 on Linux

This simple .c file:
#include <unistd.h>
void test() {
char string[40];
gethostname(string,40);
}
... when compiled normally, works fine:
$ cc -Wall -c -o tmp.o tmp.c
$
... but when compiled in C99 mode, gives a warning:
$ cc -Wall -std=c99 -c -o tmp.o tmp.c
tmp.c: In function `test':
tmp.c:5: warning: implicit declaration of function `gethostname'
$
The resultant .o file is fine, and linking works. I'd just like to get rid of the warning. I can achieve this in a hacky way, by putting declarations in my own .h file.
What is it about C99 that means the declarations in unistd.h don't get included?
Can this be overcome, without giving up the niceness of C99?
I see the same problem for other standard libs.
You may need to define some macros in a particluar way to get the prototype for gethostname()
From man gethostname:
Feature Test Macro Requirements for
glibc (see feature_test_macros(7)):
gethostname(): _BSD_SOURCE || _XOPEN_SOURCE >= 500
sethostname(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)
So:
#define _BSD_SOURCE
#include <unistd.h>
void test() {
char string[40];
gethostname(string,40);
}
The gory details:
If you don't specify the -std-c99 option, then features.h (which is implicitly included by unistd.h) will default to setting _BSD_SOURCE in such a way that the prototype for gethostname() gets included. However, specifying -std=c99 causes the compiler to automatically define __STRICT_ANSI__, which in turn causes features.h to not define _BSD_SOURCE, unless you force it with your own feature macro definition (as above).
gethostname( ) is not a standard C function (it's not mentioned anywhere in the C99 standard), so the symbol is correctly not defined when compiling to the standard.
If you're using the gcc toolchain, use -std=gnu99 and you'll get the behavior you want.
Alternatively, looking at <features.h>, it seems like you could use -D_GNU_SOURCE or -D_XOPEN_SOURCE=500 to get the desired behavior.
Read man gethostname. It says in the Feature Test Macro Requirements, that _BSD_SOURCE (or _XOPEN_SOURCE>500) is required to pull gethostname from unistd.h.
Next read man feature_test_macros. You will find that -std=c99 turns on __STRICT_ANSI__ which in turns off _BSD_SOURCE. This means you can't get gethostname from unistd.h unless you define _BSD_SOURCE again. I usually place _GNU_SOURCE on my command line (i.e. gcc -D_GNU_SOURCE -std=c99 file.c) for most things, which turns on _BSD_SOURCE as well.
P.S. The manual page contains an example program which can print the current ft-macros. You might compile and run it for some compiler settings.

C-library not linking using gcc/g++

I have a c-library which I use in gcc. The library has the extension .lib but is always linked as a static library. If i write a program which uses the library as c-code, everything as a-ok. If I however rename the file to .cpp (doing simple stuff that works in both c/c++) I get undefined reference. These are simple small programs I write for testing purposes so no fancy stuff. I compile using:
gcc -g -Wall -I <path to custom headers> -o program main.c customlibrary.lib -lm -lpthread
The above works like a charm. However:
g++ -g -Wall -I <path to custom headers> -o program main.cpp customlibrary.lib -lm -lpthread
or
gcc -g -Wall -I <path to custom headers> -o program main.cpp customlibrary.lib -lm -lpthread -lstdc++
results in undefined reference to any function in customlibrary.lib. I tried creating a symbolic link named customlibrary.a but no luck.
Why won't g++ find recognize my library. Unfortunately I have no access to the source code of the libraries but linking a c-lib to c++ should not be a problem right?
Your library appears to have an API that assumes it will be called from C, not C++. This is important because C++ effectively requires that the symbols exported from a library have more information in them than just the function name. This is handled by "name mangling" the functions.
I assume your library has an include file that declares its public interface. To make it compatible with both C and C++, you should arrange to tell a C++ compiler that the functions it declares should be assumed to use C's linkage and naming.
A likely easy answer to test this is to do this:
extern "C" {
#include "customlibrary.h"
}
in your main.cpp instead of just including customlibrary.h directly.
To make the header itself work in both languages and correctly declare its functions as C-like to C++, put the following near the top of the header file:
#ifdef __cplusplus
extern "C" {
#endif
and the following near the bottom:
#ifdef __cplusplus
}
#endif
The C++ compiler performs what is known as name-mangling - the names that appear in your code are not the same ones as your linker sees. The normal way round this is to tell the compiler that certain functions need C linkage:
// myfile.cpp
extern "C" int libfun(); // C function in your library
or do it for a whole header file:
// myfile.cpp
extern "C" {
#include "mylibdefs.h" // defs for your C library functions
}
Does your header file have the usual
#ifdef __cplusplus
extern "C" {
#endif
// ...
#ifdef __cplusplus
} /* extern "C" */
#endif
to give the library functions C linkage explicitly.
.cpp files are compiled with C++ linkage i.e. name mangling by default.

Resources