How to write program during compiling? - c

Write a small C program, which while compiling takes another program
from input terminal, and on running gives the result for the second
program. (NOTE: The key is, think UNIX).
Suppose, the program is 1.c
Then, while compiling
$ cc -o 1 1.c
int main()
{
printf("Hello World\n");
}
^D
$ ./1
Hello World
$

This is an old parlaour trick I guess
My program, tty.c:
#include "/dev/tty"
Shell:
$ gcc tty.c
int main() {
printf("Hey\n");
} *Ctrl-D here*
In file included from tty.c:1:
/dev/tty: In function ‘main’:
/dev/tty:2: warning: incompatible implicit declaration of built-in function ‘printf’
$./a.out
Hey

The most reasonable way to make compilation read a file would be #include, but it's not obvious to me how to make it read standard input in a portable way on all Unix systems (easy in Linux, thanks to the magic of /proc!, but that wouldn't be portable).

Related

How to use gcc sanitizers

Why does this not work?:
prog.c file
#include <stdio.h>
int main(void)
{
int i, j;
printf("\n%d\n%d\n", i, j);
return 0;
}
debug file:
#!/bin/bash
g++ -Wall -Wextra -Wpedantic -O0 -g3 -fsanitize=address -o temp/debug.out src/prog.c
./temp/debug.out
running:
./debug
prog.c: In function ‘main’:
prog.c:6:9: warning: ‘i’ is used uninitialized in this function [-Wuninitialized]
printf("\n%d\n%d\n", i, j);
^~~~~~~~~~~~~~~~~~~~~~~~~~
prog.c:6:9: warning: ‘j’ is used uninitialized in this function [-Wuninitialized]
0
0
==90==LeakSanitizer has encountered a fatal error
==90==HINT: For debugging, try setting environment variable LSAN_OPTION=verbosity=1:log_threads=1
==90==LeakSanitizer does not work under ptrace (strace, gdb, etc)
I'm new to using debuging tools but there isn't much to read on this topic except man pages of compilers. So please can someone help me?
This was executed on Windows 10 subsystem for linux (Ubuntu) on freshly openned terminal.
I'd like to use -fno-sanitize=all option I found in man pages of gcc but it doesn't seem to say a word on any mistake I came up with.
I found out it was problem of WSL i used (I didn't think it was important to say i use one)
Turns out i need to write LSAN_OPTION=verbosity=1:log_threads=1; g++ -Wall...

How to write a C program that compiles other C programs using GCC?

I want my program to do the same thing as the terminal commands below:
gcc program1.c -o p1 funcs.c
gcc program2.c -o p1 funcs.c
This is what I've been experimenting with: Making a C program to compile another
I got as far so calling my program (./"programName") in the terminal that it replaced the need for me too type gcc but needing me too type in the rest.
You can use the Linux and POSIX APIs so read first Advanced Linux Programming and intro(2)
You could just run a compilation command with system(3), you can use snprintf(3) to build the command string (but beware of code injection); for example
void compile_program_by_number (int i) {
assert (i>0);
char cmdbuf[64];
memset(cmdbuf, 0, sizeof(cmdbuf));
if (snprintf(cmdbuf, sizeof(cmdbuf),
"gcc -Wall -g -O program%d.c fun.c -o p%d",
i, i)
>= sizeof(cmdbuf)) {
fprintf(stderr, "too wide command for #%d\n", i);
exit(EXIT_FAILURE);
};
fflush(NULL); // always useful before system(3)
int nok = system(cmdbuf);
if (nok) {
fprintf(stderr, "compilation %s failed with %d\n", cmdbuf, nok);
exit(EXIT_FAILURE);
}
}
BTW, your program could generate some C code, then fork + execve + waitpid the gcc compiler (or make), then perhaps even dlopen(3) the result of the compilation (you'll need gcc -fPIC -shared -O foo.c -o foo.so to compile a dlopenable shared object...). MELT is doing exactly that. (and so does my manydl.c which shows that you can do a big lot of dlopen-s ...)
You can use exec family function or you can directly execute shell command by using system() method
There is build in functionality in Makefile.
All you would have to call is make.
How to: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
Great stackoverflow question: How do I make a simple makefile for gcc on Linux?

Error when compiling with GCC

Every time I compile I get the following error message:
Undefined reference to ( function name )
Let's say I have three files: Main.c, printhello.h, printhello.c. Main.c calls function print_hello(), which returns "Hello World". The function is defined in printhello.c.
Now, here's the following code of printhello.h:
#ifndef PRINTHELLO_H
#define PRINTHELLO_H
void print_hello();
#endif
I am sure this code is fine. I still don't know why is it giving me the error, though. Can you help me?
Undefined references are the linker errors. Are you compiling and linking all the source files ? Since the main.c calls print_hello(), linker should see the definition of it.
gcc Main.c printhello.c -o a.out
The error is, I think, a linker error rather than a compiler error; it is trying to tell you that you've not provided all the functions that are needed to make a complete program.
You need to compile the program like this:
gcc -o printhello Main.c printhello.c
This assumes that your file Main.c is something like:
#include "printhello.h"
int main(void)
{
print_hello();
return 0;
}
and that your file printhello.c is something like:
#include "printhello.h"
#include <stdio.h>
void print_hello(void)
{
puts("Hello World");
}
Your declaration in printhello.h should be:
void print_hello(void);
This explicitly says that the function takes no parameters. The declaration with the empty brackets means "there is a function print_hello() which returns no value and takes an indeterminate (but not variadic) list of arguments", which is quite different. In particular, you could call print_hello() with any number of arguments and the compiler could not reject the program.
Note that C++ treats the empty argument list the same as void print_hello(void); (so it would ensure that calls to print_hello() include no arguments), but C++ is not the same as C.
Another way to do it is to explicitly build object files for the printhello:
gcc -c printhello.c -o printhello.o
gcc -o Main main.c printhello.o
This has the added benefit of allowing other programs to use the print_hello method
It seems that the error is from the linker and not the compiler. You need to compile and link both the source files. I think what you are doing is simply including the header file in Main.c and you are not compiling the printhello.c
You need to :
gcc Main.c printhello.c -o myprog
or
construct the object files first
gcc -c printhello.c
gcc -c Main.c
then link them
gcc Main.o printhello.o

"int main (vooid)"? How does that work?

I recently had to type in a small C test program and, in the process, I made a spelling mistake in the main function by accidentally using vooid instead of void.
And yet it still worked.
Reducing it down to its smallest complete version, I ended up with:
int main (vooid) {
return 42;
}
This does indeed compile (gcc -Wall -o myprog myprog.c) and, when run, it returns 42.
How exactly is this valid code?
Here's a transcript cut and pasted from my bash shell to show what I'm doing:
pax$ cat qq.c
int main (vooid) {
return 42;
}
pax$ rm qq ; gcc -Wall -o qq qq.c ; ./qq
pax$ echo $?
42
It's simply using the "old-style" function-declaration syntax; you're implicitly declaring an int parameter called vooid.
It's valid code, because myprog.c contains:
int main (vooid) // vooid is of type int, allowed, and an alias for argc
{
return 42; // The answer to the Ultimate Question
}
vooid contains one plus the number of arguments passed (i.e., argc). So, in effect all you've done is to rename argc to vooid.
In C, the default type for a function argument is int. So, your program is treating the word vooid as int main(int vooid), which is perfectly valid code.
It is only gcc -std=c89 -Wall -o qq qq.c and gcc -std=gnu89 -Wall -o qq qq.c don't emit a warning. All the other standards emit a warning about implicit type int for vooid.
int main(chart) behaves the same way as does int main (vooid).
return vooid; returns the number of command line arguments.
I tested with gcc 4.4.5 on Debian testing system.

Compile string of C code

Really off the wall question here, but is there a way to compile a string of C code in GCC without any medium to hold that string (eg. a source file)?
Something along the lines of:
$ gcc "#include <stdio.h> int main( void ){ printf('hello world'); return 0;}" -o test
Feels really dirty, but it would be really nice if there was some simple way to do that type of thing.
If you use - as the input file in the command line, gcc reads from standard input. Since there is no file name extension gcc could use to find out the language that should be compiled, it has to be specified with the -x flag:
$ gcc -x c -o tst - <<EOF
> #include <stdio.h>
> int main(void) {
> printf("Hello world\n");
> }
> EOF
$ ./tst
Hello world
I confess to sometimes highlighting code and using:
(cat preamble.hpp; xsel) | g++ -x c++ - && ./a.out
The same works with "-x c" for C.

Resources