Dave Cope's Homepage
   Main | Personal | Photo Gallery | Projects | Linux | Employment Info. | Links | Misc. | About e-mail  

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.



This site was designed and coded by Dave Cope - © 1998-2003
Syntax highlighting performed by Beautifier