Quine Tutorial
Introduction
Creating a program whose output is the program itself isn't (at least
initially) a trivial task. However, it is actually quite simple once you
figure it out. In fact, it took me about 15min to create the final program. I
decided to create a tutorial on how to generate such a program.
The Quine Page has many
quines for various languages. The page includes an extremely short program
written in C that reproduces itself. Instead of trying to break some sort of
record, my intent is to create a quine whose creation can be easily
understood.
Note:To keep things more readable, I ran "indent" on the source code
to make it more readable on line. To get the unmodified source code and
Makefile, please download quine.tar.gz. You will
need to make a couple small changes to the make file depending on what platform
and compiler you are using.
End Result
First of all, I am going to show you the "final" program. This is the end
result of the tutorial. However, generating this program by hand would be
extremely difficult, and it is really hard to change if you make a mistake.
Source: quine.c char body_c[] = {
35, 105, 110, 99, 108, 117, 100, 101, 32, 34, 115, 116, 100, 105, 111, 46,
104, 34, 10, 105, 110, 116, 32, 109, 97, 105, 110, 40, 41, 10, 123, 10,
32, 32, 32, 32, 105, 110, 116, 32, 105, 59, 10, 32, 32, 32, 32, 112, 114,
105, 110, 116, 102, 40, 32, 34, 99, 104, 97, 114, 32, 98, 111, 100, 121,
95, 99, 91, 93, 32, 61, 32, 92, 110, 123, 92, 110, 34, 32, 41, 59, 10, 32,
32, 32, 32, 102, 111, 114, 40, 32, 105, 32, 61, 32, 48, 59, 32, 105, 32,
60, 32, 115, 105, 122, 101, 111, 102, 40, 98, 111, 100, 121, 95, 99, 41,
59, 32, 105, 43, 43, 32, 41, 10, 32, 32, 32, 32, 123, 10, 32, 32, 32, 32,
32, 32, 32, 32, 112, 114, 105, 110, 116, 102, 40, 32, 34, 37, 100, 44, 32,
34, 44, 32, 98, 111, 100, 121, 95, 99, 91, 105, 93, 32, 41, 59, 10, 32,
32, 32, 32, 125, 10, 32, 32, 32, 32, 112, 114, 105, 110, 116, 102, 40, 32,
34, 125, 59, 92, 110, 34, 32, 41, 59, 10, 32, 32, 32, 32, 102, 119, 114,
105, 116, 101, 40, 32, 98, 111, 100, 121, 95, 99, 44, 32, 115, 105, 122,
101, 111, 102, 40, 98, 111, 100, 121, 95, 99, 41, 44, 32, 49, 44, 32, 115,
116, 100, 111, 117, 116, 32, 41, 59, 10, 32, 32, 32, 32, 114, 101, 116,
117, 114, 110, 32, 48, 59, 10, 125, 10,
};
#include "stdio.h"
int
main ()
{
int i;
printf ("char body_c[] = \n{\n");
for (i = 0; i < sizeof (body_c); i++)
{
printf ("%d, ", body_c[i]);
}
printf ("};\n");
fwrite (body_c, sizeof (body_c), 1, stdout);
return 0;
}
How to get there...
Let me explain the structure of quine.c. First, the program contains an
array of data. This data is equivalent to the text that makes up the body
of the program. The data is followed by the main loop of the program that
outputs the contents of the data array as a C array (i.e. "body_c[] = { ... };")
and then the data array as plain text (i.e. "int main () { ... }"). I think the
actual execution of the program is pretty easy to follow, and it should be easy
to convince yourself that it outputs itself.
Now the tricky part is to figure out how to easily create this program from
scratch. The first step is to create the body of the program. After all, the
data in the program is the same as the program body. So it is a lot easier to
create the body first. Here is the body of the program:
Source: body.c #include "stdio.h"
int main()
{
int i;
printf( "char body_c[] = \n{\n" );
for( i = 0; i < sizeof(body_c); i++ )
{
printf( "%d, ", body_c[i] );
}
printf( "};\n" );
fwrite( body_c, sizeof(body_c), 1, stdout );
return 0;
}
As you can see, the body of the program is quite simple. I guess the only
strange thing is that it refers to an array called "body_c" which isn't defined
anywhere. But don't worry, we will take care of that soon. In fact, body.c
isn't supposed to be executed at all. Just think of it as a data file.
Now, the data array "body_c" can be generated from body.c. I chose to use
the utility xxd to convert body.c into a C character array. If you
don't want to use xxd it would be really easy to write a C program
to do the same thing. So it isn't really necessary to use any external tools
to make this quine. Here is the output of xxd -i body.c body.inc:
Source: body.inc unsigned char body_c[] = {
0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x22, 0x73, 0x74,
0x64, 0x69, 0x6f, 0x2e, 0x68, 0x22, 0x0a, 0x69, 0x6e, 0x74, 0x20, 0x6d,
0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70,
0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x20, 0x22, 0x63, 0x68, 0x61, 0x72,
0x20, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x5b, 0x5d, 0x20, 0x3d, 0x20,
0x5c, 0x6e, 0x7b, 0x5c, 0x6e, 0x22, 0x20, 0x29, 0x3b, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x66, 0x6f, 0x72, 0x28, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30,
0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66,
0x28, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x29, 0x3b, 0x20, 0x69, 0x2b,
0x2b, 0x20, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66,
0x28, 0x20, 0x22, 0x25, 0x64, 0x2c, 0x20, 0x22, 0x2c, 0x20, 0x62, 0x6f,
0x64, 0x79, 0x5f, 0x63, 0x5b, 0x69, 0x5d, 0x20, 0x29, 0x3b, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x69,
0x6e, 0x74, 0x66, 0x28, 0x20, 0x22, 0x7d, 0x3b, 0x5c, 0x6e, 0x22, 0x20,
0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x77, 0x72, 0x69, 0x74,
0x65, 0x28, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x2c, 0x20, 0x73,
0x69, 0x7a, 0x65, 0x6f, 0x66, 0x28, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63,
0x29, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74,
0x20, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x30, 0x3b, 0x0a, 0x7d, 0x0a
};
unsigned int body_c_len = 260;
The next step is to basically paste the two files together to create a
program capable of generating the quine. This could be done entirely by hand,
but I always prefer to automate programming tasks. Here is the source for my
quine generator:
Source: quine_gen.c #include "body.inc"
#include "body.c"
As you can see, it effectively pastes together the data array (body.inc) and
the body of the quine (body.c).
Now, compile and run quine_gen to create the final quine's source.
Here is the output you should get from quine_gen:
Source: quine.c char body_c[] = {
35, 105, 110, 99, 108, 117, 100, 101, 32, 34, 115, 116, 100, 105, 111, 46,
104, 34, 10, 105, 110, 116, 32, 109, 97, 105, 110, 40, 41, 10, 123, 10,
32, 32, 32, 32, 105, 110, 116, 32, 105, 59, 10, 32, 32, 32, 32, 112, 114,
105, 110, 116, 102, 40, 32, 34, 99, 104, 97, 114, 32, 98, 111, 100, 121,
95, 99, 91, 93, 32, 61, 32, 92, 110, 123, 92, 110, 34, 32, 41, 59, 10, 32,
32, 32, 32, 102, 111, 114, 40, 32, 105, 32, 61, 32, 48, 59, 32, 105, 32,
60, 32, 115, 105, 122, 101, 111, 102, 40, 98, 111, 100, 121, 95, 99, 41,
59, 32, 105, 43, 43, 32, 41, 10, 32, 32, 32, 32, 123, 10, 32, 32, 32, 32,
32, 32, 32, 32, 112, 114, 105, 110, 116, 102, 40, 32, 34, 37, 100, 44, 32,
34, 44, 32, 98, 111, 100, 121, 95, 99, 91, 105, 93, 32, 41, 59, 10, 32,
32, 32, 32, 125, 10, 32, 32, 32, 32, 112, 114, 105, 110, 116, 102, 40, 32,
34, 125, 59, 92, 110, 34, 32, 41, 59, 10, 32, 32, 32, 32, 102, 119, 114,
105, 116, 101, 40, 32, 98, 111, 100, 121, 95, 99, 44, 32, 115, 105, 122,
101, 111, 102, 40, 98, 111, 100, 121, 95, 99, 41, 44, 32, 49, 44, 32, 115,
116, 100, 111, 117, 116, 32, 41, 59, 10, 32, 32, 32, 32, 114, 101, 116,
117, 114, 110, 32, 48, 59, 10, 125, 10,
};
#include "stdio.h"
int
main ()
{
int i;
printf ("char body_c[] = \n{\n");
for (i = 0; i < sizeof (body_c); i++)
{
printf ("%d, ", body_c[i]);
}
printf ("};\n");
fwrite (body_c, sizeof (body_c), 1, stdout);
return 0;
}
If you compile this file, you should now have an executable whose output is
precisely quine.c!
I hope my description of how to create a quine is easy to understand. If you
have any questions or suggestions regarding this page, send me an e-mail.
|