How to change #include with #define in c? - c

Is there a way to change the #include syntax? Here's an example of I am trying to reach out with this.
#define begin {
#define end }
#define import #include
import <stdio.h>
int main() begin
return 0;
end

Not really. At least not in a way that would fill any practical meaning.
First, the preprocessor is run and it till change "import" to "#include", and then it gives the output to the compiler. But the compiler does not understand preprocessor directives. Also, the C language does not have any functionality to include files. That's supposed to be handled by the preprocessor.
So one thing that CAN be done, although it's not something you should ever do in production code is to run the preprocessor twice. It's very likely that this approach will yield bugs that are tricky to find.
$ cat a.c
#define begin {
#define end }
#define import #include
import <stdio.h>
int main() begin
return 0;
end
$ gcc -E a.c > b.c
$ cat b.c
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "a.c"
#include <stdio.h>
int main() {
return 0;
}
$ gcc b.c
$
You could simplify the above to one command like this:
gcc -E a.c | gcc -xc -
(The final dash is important)

Per C 2018 6.10.3.4 3, after a macro has been substituted:
The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one,…
Thus, defining a macro to expand to #include will not result in an #include directive being processed.

Related

Search C function definition using Compilation Error

I am working on a C project which has same definition of C function in multiple places. I am trying to get the definition of C function using compilation errors like "error: conflicting types for foo_func()"; which also provides header file declaration as "bar_file.h:< line no >: note: previous declaration of foo_func() was here". I want to rely on compilation error instead of grep like commands because compiler knows for sure which function it is linking with, so I can be sure of the function definition which is being used.
I am able to locate the header file with deliberately applying compilation error. Is there a way to use the similar technique to find the definition of function I am using at compilation time?
Example: Let's find the header file which has the declaration of the function we are using. We can end up into the following compilation error by purposeful introduction of multiple definition with a known parameter mismatch.
$ gcc -Wall -Wextra -c exmpl_01.c -I./
exmpl_01.c:5: error: conflicting types for ‘call_func_other_file’
exmpl_01.h:1: note: previous declaration of ‘call_func_other_file’ was here
$ head -4 exmpl_01.c
#include <stdio.h>
#include "exmpl_01.h"
int call_func(void);
int call_func_other_file(char *);
$ cat exmpl_01.h
int call_func_other_file(void);
You can try deliberately addind a duplicate definition in a separate translation unit. Then link all object files together (compiled with debugging symbols enabled). The linker will tell you in what file and on what line the duplicate is defined.
Maybe you are looking for -E switch ?
// a.h
int a() {
return 1;
}
and then, we have
// main.c
#include "a.h"
int main() {
return a();
}
and, with -E you can get
> gcc -E main.c
# 1 "main.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 331 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "main.c" 2
# 1 "./a.h" 1
int a() {
return 1;
}
# 2 "main.c" 2
int main() {
return a();
}
now, let's say our source has another file
// b.h
float a() {
return 1.0;
}
and main.c is slightly different
#include "a.h"
#include "b.h"
int main() {
return a();
}
you will be able to see the last definition of function
gcc -c -E main.c
# 1 "main.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 331 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "main.c" 2
# 1 "./a.h" 1
int a() {
return 1;
}
# 2 "main.c" 2
# 1 "./b.h" 1
float a() {
return 1.0;
}
# 3 "main.c" 2
int main() {
return a();
}
But, I am not sure whether this is something you are looking for ;)
Hmm ... if you want to stop at certain point, maybe this one will help you:
#include "a.h"
#include "b.h"
int main() {
a();
#error Quit!
printfun("aaa");
}
and this way, compilation will fail a #error
> gcc -c -Wfatal-errors main.c
In file included from main.c:2:
./b.h:1:7: fatal error: conflicting types for 'a'
float a() {
^
./a.h:1:5: note: previous definition is here
int a() {
^
1 error generated.
Or, you can simply introduce some sort of fake type
#include "a.h"
struct fake_type {
int fake_component;
};
struct fake_type *a();
int main() {
a();
}
and enforce the error
> gcc -c -Wfatal-errors main.c
main.c:7:19: fatal error: conflicting types for 'a'
struct fake_type *a();
^
./a.h:1:5: note: previous definition is here
int a() {
^
1 error generated.

Why is the value of macro is not changing in a called function?

I came across a program on one C aptitude question site
#define i 20
void fun();
int main(void)
{
printf("%d..",i);
fun();
printf("%d",i);
}
void fun() {
#undef i;
#define i 30
}
Here the output comes to be
20..20
But according to me it should be
20..30
Why dosen't the value of i become 30 after call to fun()?
#define i 20
void fun();
int main(void)
{
printf("%d..",i);
#define i 50
printf("%d",i);
}
But if i compile and run above program the output comes to be 20..50
So now how macro value is changing at runtime.
Macros cannot be changed at runtime. In your program the macro is changed by the preprocessor once before compiling so it's value in the compiled program is 30.
You can read about it here.
void fun() {
#undef i;
#define i 30
}
will actually be an empty function, the preprocessed program would be
void fun();
int main(void)
{
printf("%d..",20);
fun();
printf("%d",20);
}
void fun() {
}
so you can see that the output is correct.
To generate the above preprocessed program you can use this with gcc
gcc -E -P source.c
is actually an empty function
The proprocessor's directives are completely independent and separate to program's ordinary flow. The reason for this lies in translation phases, that are specified in C Standard. The processing stage (phases 1-4) is performed conceptually before proper compilation (phase 7). The unit obtained after preprocessing stage is called as translation unit and you can think of it as "starting point" for further translation, including proper compilation.
Your compiler may allow to inspect particular translation unit, so you get how it looks effectively. For example gcc has -E flag for that (by default, it outputs so called linemarkers, but you can suppress them using -P flag). In your case it might look as:
$ gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
void fun();
int main(void)
{
printf("%d..",20);
fun();
printf("%d",20);
}
test.c:13:9: warning: extra tokens at end of #undef directive
void fun() {
}

Expanding a single C pre-processor directive

I need to expand a single preprocessor directive, for example:
Having a source file and two headers, I want to expand only one define from one specific header, leaving all other include and define intact.
The main idea is that, given code similar to this:
defs.h:
#define FOO(X,op) int X(int a,int b) { return a op b; }
other_file.h:
#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4
#define FIVE 5
main.c:
"file: main.c "
#include <stdio.h>
#include "defs.h"
#include "other_file.h"
FOO(add,+)
FOO(sub,-)
FOO(mul,*)
FOO(div,/)
int main()
{
printf("%d\n",add(ONE,TWO));
printf("%d\n",sub(THREE,FOUR));
printf("%d\n",mul(FIVE,FIVE));
printf("%d\n",div(25,FIVE));
return 0;
}
I would have the main.c output with the same includes, but with FOO expanded to the created functions. I known the example is silly, but I intend to run it on a larger code database.
The motivation to do it is to run cccc in functions that are defined within macros. The easiest way to run it is to expand those macros. I also welcome alternative ways to do this.
You can play with the -E, -nostdinc, -nostdinc++ and -fpreprocessed parameters of GCC.
For your example, you can run:
gcc -E -nostdinc -fpreprocessed main.c
And the output would be:
# 1 "main.c"
#include <stdio.h>
#include "defs.h"
#include "other_file.h"
FOO(add,+)
FOO(sub,-)
FOO(mul,*)
FOO(div,/)
int main()
{
printf("%d\n",add(ONE,TWO));
printf("%d\n",sub(THREE,FOUR));
printf("%d\n",mul(FIVE,FIVE));
printf("%d\n",div(25,FIVE));
return 0;
}
If the headers are not that complex, like in your example, you can force gcc to preprocess the whole file even with some missing macros. E.g.:
cp other_file.h other_file.h_orig
echo "" > other_file.h
gcc -E -nostdinc main.c
Output:
# 1 "main.c"
# 1 "<command-line>"
# 1 "main.c"
main.c:1:19: error: no include path in which to search for stdio.h
#include <stdio.h>
^
# 1 "defs.h" 1
# 3 "main.c" 2
# 1 "other_file.h" 1
# 4 "main.c" 2
int add(int a,int b) { return a + b; }
int sub(int a,int b) { return a - b; }
int mul(int a,int b) { return a * b; }
int div(int a,int b) { return a / b; }
int main()
{
printf("%d\n",add(ONE,TWO));
printf("%d\n",sub(THREE,FOUR));
printf("%d\n",mul(FIVE,FIVE));
printf("%d\n",div(25,FIVE));
return 0;
}
It will remove the header inclusions, though... and will print you an error on std headers, that goes to stderr instead of stdout.
This works for your small example, but on larger codebase you may face some problems...
Here is a brief summary of the parameters from the manual (of GCC 4.8.2) :
-E: Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which
is sent to the standard output.
-fpreprocessed: Indicate to the preprocessor that the input file has already been preprocessed. This suppresses things like macro
expansion, trigraph conversion, escaped newline splicing, and
processing of most directives.
-nostdinc: Do not search the standard system directories for header files. Only the directories you have specified with -I options.
-nostdinc++: Do not search for header files in the standard directories specific to C++, but do still search the other standard
directories.
Our DMS Software Reengineering Toolkit with its C Front End will do this.
DMS provides general purpose program parsing/analysis infrastructure. The C Front End builds on that to provide a full-function C front, complete with C preprocessor.
Normally, the DMS C preprocessor acts just like the standard one: it preprocesses everything, producing a substituted stream of tokens. Unusually, it can be configured to NOT process conditionals (this is all-or-nothing), or to expand only designated macros. In particular, it accepts a custom #pragma that declares that a macro should (not) expand.
It isn't clear to me that this is worth the effort. Yes, a metrics tool might produce more accurate answers in certain places where some macro is heavily used, if you believe that the macro should be non-opaque. If you think the macro is essentially just a funny-looking subroutine, then expanding this macro is like inlining a function body, and you would not do that to compute metrics.

I don't want to preprocess specific macros. It should not replace it with its value. Is it possible?

Example =
#define a 100
#define b 200
main()
{
int c=a+b;
}
After preprocessing
Output-
#define a 100
main()
{
int c=a+200;
}
You could try refactoring the macros to allow external configuration, i.e.
/* config.h */
/* set defaults for a and b */
#ifndef a
#define a 100
#endif
#ifndef b
#define b 200
#endif
and
/* main.c */
#include "config.h"
int main(void)
{
int c = a + b;
}
Then you can set the macros externally when building, for instance like this:
$ gcc -E -Da=a main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"
# 1 "config.h" 1
# 4 "main.c" 2
int main(void)
{
int c = a + 200;
}
$ gcc -E -Db=b main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"
# 1 "config.h" 1
# 4 "main.c" 2
int main(void)
{
int c = 100 + b;
}
Now, of course you don't have to use a separate configuration header, but I'd recommend it from a maintenance perspective, it will make it easier to keep track of available configuration settings and their defaults.
#define a 100
#define b 200
main()
{
#undef b
int c=a+b;
}
No. What's your real goal?
If you want to do, it's better to make some script to do that.
If you don't want to preprocess a macro, just don't use it:
#define a 100
//#define b 200
int main()
{
int c = a + 200;
return 0;
}
The purpose of preprocessing is to process the preprocessing directives. I don't know of any way to keep a specific preprocessing directive, especially because the next step, compilation, doesn't know anything about these.
This is another reason why you should be careful when using macros -- when the name is found in the source, then it is substituted, no matter what:
#define a 100
main()
{
int a; // Compilation error happens here
....
}
Regarding Peter Miehle's answer, unifdef can be used to partially process #if and #ifdef directives, but it cannot be used to selectively expand macros. See http://dotat.at/prog/unifdef

#define f(g,g2) g##g2

#define f(g,g2) g##g2
main()
{
int var12=100;
printf("%d",f(var,12));
}
The above program prints 100 in c by concatenating var and 12. How does g##g2 work??
## just pastes tokens together. It is a preprocessor directive.
E.g.
#define PASTE(a,b) a##b
int i=PASTE(1,2); /* int i=12; */
## is the preprocessor "command" for concatenating what comes before and after.
This is token pasting, described here for gcc. Token pasting is done by the preprocessor, not the compiler.
So after preprocess it will look like this:
main()
{
int var12=100;
printf("%d",var12);
}
Concatenation is being performed by the preprocessor because you used the ## command.
When you are unsure what the preprocessor is doing you can ask gcc to stop after it has run the preprocessor. Since this is before the compiler runs, the output is fairly easy to understand.
For example, assume you have a file pre.c
#define FOO 123
#define CONCAT(x,y) x##y
#define STRING(x) #x
void main()
{
int a = FOO;
int b = CONCAT(123,4567);
char* c = STRING(IGetQuoted);
}
You can produce the preprocessor output by passing the -E option to gcc.
$ gcc -E pre.c
# 1 "pre.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "pre.c"
void main()
{
int a = 123;
int b = 1234567;
char* c = "IGetQuoted";
}
Keep in mind that #include will pull in the contents of the file it specifies and can make the preprocessor output rather long.

Resources