I want to write a C program for implementing the include functionality of the preprocessor.
Example:
In header.h I have this code:
char *test (void);
And in program.c:
int x;
#include "header.h"
int
main (void)
{
puts (test ());
}
The input is program.c.
The output must be :
int x;
char *test (void);
int
main (void)
{
puts (test ());
}
How can I do this?
You'd need to read the input file line by line. Check to see if the line starts with #include (with optional leading whitespace). If not, print the line you've read. If so, open the specified file instead, and run this same algorithm on it (to handle secondary #includes).
you can run gcc -E "your source files", and then filter the line included "#",the left is your wanted, and the macros is replaced by its real forms.
for example:
gcc -E hello.c|sed '/# .,$/d' > a.c
a.c is your wanted file.
when use gcc
gcc -E -P program.c
or
cpp -P program.c
when use Visual c
cl /EP program.c
Related
How to use a variable from a batch file and send the value to a variable in a C file/program?
I absolutely do not know how to do this, and I don't know if it is even possible.
I am thinking about something like this:
Batch file:
#echo off
set name= %1
::somehow set a variable in myfile.c to "name"'s value
gcc myfile.c -o readf
.\readf
C file:
#include <stdio.h>
int main() {
char(or any other) name[] = /* the value of "name" in the batch file */
printf(name);
return 0;
}
As pointed out by #kopecs, it seem that you want to define a macro in the command line while compiling your code. This would be useful if you want to define some constant that will be included in the binary for future execution, but not if you simply want to get argument from the command line.
Modify your code the following way to use the preprocessor
#include <stdio.h>
#ifndef VARIABLE
// In case you want to define a default value for your VARIABLE
#define VARIABLE "default value"
#endif
int main() {
char(or any other) name[] = VARIABLE // VARIABLE is a preprocessing macro that will be defined by the compiler
printf(name);
return 0;
}
Then invoke the compiler with the following preprocessor option
#echo off
set name=%1
::somehow set a variable in myfile.c to "name"'s value
gcc myfile.c -o readf -D "VARIABLE=%name%" -Wall -Wextra -pedantic
.\readf
Documentation quote for the argument
-D name=definition
The contents of definition are tokenized and processed as if they appeared during translation phase three in a ‘#define’ directive. In particular, the definition is truncated by embedded newline characters.
If you are invoking the preprocessor from a shell or shell-like program you may need to use the shell’s quoting syntax to protect characters such as spaces that have a meaning in the shell syntax.
If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses are meaningful to most shells, so you should quote the option. With sh and csh, -D'name(args…)=definition' works.
-D and -U options are processed in the order they are given on the command line. All -imacros file and -include file options are processed after all -D and -U options.
However, I would recommend using command line argument for your program, that would be more flexible and avoid to recompile it each time you want to change it (unless you want to redistribute the binary with the hardcoded string).
#include <stdio.h>
int main(int argc, char* argv[]) {
// add some sanity checking against argc before getting the value in argv
char(or any other) name[] = argv[1];
printf(name);
return 0;
}
and after compiling your code the with
gcc myfile.c -o readf -Wall -Wextra -pedantic
Just invoke with
.\readf name_value
I would like to know if it's possible to indicate for gcc some flag that include a directory for different kind of files, like .wav or .txt. Then in my code I wouldn't need to indicate the directory to read the file.
Pass it as a macro on the compile line, e.g.:
#include <stdio.h>
#define qstr(a) str(a)
#define str(a) #a
int main(void)
{
printf("The path is %s\n", qstr(MY_FILE_PATH));
return 0;
}
Then compile as:
gcc -DMY_FILE_PATH="`pwd`/mymediadir/mywavfilesdir" test.c -o test
When run gives:
./test
The path is /home/joe/tmp/mymediadir/mywavfilesdir
I need to find the built-in functions used in our program from a specific header file.
For example, I have the C file below:
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
printf("a = %d\n", a);
}
If I given the stdio.h header file to any command, it needs to give the output as below:
scanf
printf
Is there any built-in command to get this?
Or any options available in the gcc or cc command to get this?
If you are using GCC as compiler, you can run this command:
echo "#include <stdio.h>" | gcc -E -
This will print many lines from the stdio.h header, and from the files that are included by that header, and so on.
Some lines look like #line …, they tell you where the following lines come from.
You can analyze these lines, but extracting the functions from them (parsing) is quite complicated. But if you just want a quick, unreliable check, you could search whether these lines contain the word scanf or printf.
EDIT
As suggested in a comment, the -aux-info is more useful, but it works only when compiling a file, not when preprocessing. Therefore:
cat <<EOF >so.c
#include <stdio.h>
int main(int argc, char **argv) {
for (int i = 1; i < argc; i++) {
fprintf(stdout, "%s%c", argv[i], i < argc - 1 ? ' ' : '\n');
}
fflush(stdout);
return ferror(stdout) == -1;
}
EOF
gcc -c so.c -aux-info so.aux
Determining the function calls from your program can be done using objdump, as follows:
objdump -t so.c
The above commands give you the raw data. You still need to parse this data and combine it to only give you the data relevant to your question.
I was wondering how this works, creating a library and preloading it so a program can use it instead of the one in the include statement.
here is what I am doing and is not working so far .
//shared.cpp
int rand(){
return 33;
}
//prograndom.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
srand(time(NULL));
int i = 10;
while(i--) printf("%d\n", rand()%100);
return 0;
}
Then in the terminal:
$ gcc -shared -fPIC shared.cpp -o libshared.so
$ gcc prograndom.cpp -o prograndom
$ export LD_PRELOAD=/home/bob/desarrollo/libshared.so
and finally
$ LD_PRELOAD=/home/bob/desarrollo/libshared.so ./prograndom
which doesnt print 33, just random numbers...
Your programs are C programs, but the cpp file extension implies C++, and GCC will interpret it that way.
That's an issue because it means that your function rand (in shared.cpp) will be compiled as a C++ function, with its name mangled to include its type-signature. However, in main you #include <stdlib.h>, which has the effect of declaring:
extern "C" int rand();
and that is the rand that the linker will look for. So your PRELOAD will have no effect.
If you change the name of the file from shared.cpp to shared.c, then it will work as expected.
Other alternatives, of dubious value, are:
Declare rand to be extern "C" in your shared.cpp file. You can then compile it as C++.
Force compilation as C by using the GCC option -x c.
I am writing a jna wrapper for a c library, compiled using gcc under cygwin. Depending on how I execute the jna wrapper the java application either just hangs (if executed as unit test under eclipse) or terminates with an Invalid memory exception. The problem seems to occur only the the c library writes something to either stdout or stderr.
Here is my minimal (not) working example:
add.c
#include <stdio.h>
int add (int x, int y)
{
fprintf(stdout, "hello world\n" );
return x + y;
}
jna wrapper
public interface Add extends Library
{
Add INSTANCE = (Add) Native.loadLibrary("add", Add.class);
int add(int x, int y);
}
Compiling the c file under cygwin as follows:
gcc -g -Wall -c add.c
gcc -shared -o add.dll add.o
If I remove the fprintf line everything works fine. Both the add.dll and cygwin1.dll are in the java target folder.
You are using wrong syntax for fprintf. It is actually
int fprintf(FILE *restrict stream, const char *restrict format, ...);
You need to pass string format specifier(%s) too.