/* Description:  This program is a quine.  It is dependent on zlib to decompress
 *   the raw program data.  Due to the way the raw data is packed into ints,
 *   this program is architecture-specific: it will not run on a big-endian
 *   architecture.
 * 
 * Compile: gcc -lz annotated_quine.c
 *
 * Author:  Josh Odom (odomobo at gmail dot com)
 * Date:  Tuesday, February 16th, 2010
 */

#include <stdio.h>      /* for I/O */
#include <string.h>     /* for string manipulation */
#include <stdint.h>     /* for uint32_t */

/* zlib is used to deflate the compressed raw program data */
#include <zlib.h>


/* Below is the raw program data, in a compressed form.  This is used
 * to generate this source code, and also itself.  Note, in its raw form,
 * all percent signs ("%") are replaced with double-percent signs ("%%").
 * Also, there is a single %s where itself should be.  This is used in the
 * printf, as seen at the bottom of the program.
 */
uint32_t COMPRESSED_DATA[] = {
0x56edda78,0x38e34fdf,0xfce7be10,0x7aaea315,0x16d0d96a,0xba213a4e,0x680b049c,
0x69c1ed39,0xae597dd9,0xda64dcaa,0x59da975a,0x563fa1db,0xe337effc,0xf02d2524,
0x24feef70,0xc78f6a4a,0x337df333,0x2e00ff69,0xe64626d1,0x0a756a4e,0x2d2e75f0,
0x8ccf46e4,0x0a3d0058,0x854851f8,0xc71b803d,0x51cc53df,0x681ca8a5,0x4e4c9b05,
0x4c5a69c0,0x683722f4,0x0007046d,0x4608e6e0,0x527eb72c,0xb87904e1,0x79ad902c,
0x5bd62977,0xd765de2b,0xc5fe48b9,0x1b22a414,0xed71b0fa,0x93222f6c,0xc4c3a5cc,
0x6d0f0615,0xca9c898e,0x83a414e4,0x5032cca5,0x142981da,0x22602787,0xae148767,
0xd5f4aa14,0x25e3db3c,0xb148fbfe,0x614f0ccb,0x98702496,0x7228406d,0xe3a61c22,
0xac84f732,0x70bcf0d8,0x48a86d73,0x873b6a7f,0xa02f54bb,0x4f53e9a3,0xb3070834,
0xa4199085,0xa3553f74,0xc92e07cb,0x40b4d709,0x0c758a9b,0x853138d7,0xfa386b30,
0x3863cddd,0xc80d1c1e,0xef451fac,0x22b24aa4,0x5d60f845,0xfe6f752a,0x0ff47807,
0xdc0daa60,0xacd8eff4,0x9aa46569,0x559566d5,0xa10b08b9,0x82645e64,0x953fdd09,
0x4ef75d52,0xb7ee8651,0x71f3b1e3,0x94e79ad0,0xe2585cca,0x253b73c2,0xaad9e85f,
0x7d9da659,0x626f777a,0xe44f7427,0xa6605e3d,0x35f2ec97,0x3544c459,0x4cf0d511,
0x957a2d41,0xb838ab10,0x0cca1496,0x16329a15,0x30bab0da,0x6294c709,0x20a5944c,
0x71c24b32,0x9d29b316,0xbd0ed5bf,0xb7f15a73,0x292f5fb2,0x91c92a41,0xad8892ce,
0x9d0b299c,0xeaddbb56,0x3e283a92,0x509133cc,0xe6e94b18,0xc9316644,0x35a5f0f0,
0x9d017bdb,0x6731a5d3,0xbb7d6746,0x4320e258,0x2c2db768,0x111f55cb,0xb22eb9d8,
0x97b82614,0xc748871b,0xfc4e57d9,0x432529b9,0xd62a21c9,0xa26c9714,0xe9a9239d,
0x1556ffa9,0xb385e7af,0xdde3ef25,0xb97f7f5f,0xbabfbfba,0x7f9e5f1c,0xc1187f3d,
0xdb6cfc19,0x1c4869e8,0x490e23bc,0xedf170c7,0xcbeafafa,0xfbe6fef8,0x080d1c15,
0x85cc9451,0x278e5da9,0xe68a74c5,0x1a3661a1,0x1aa29536,0x521cd52c,0x7307de10,
0x6783a6f9,0x730f0d1f,0x13956d5c,0x90994441,0xf0eaa574,0x24b33083,0x80f8ef06,
0x461f1f9e,0x0119f85d,0x4390058f,0x498cd87a,0xd3f748ed,0x442f05bf,0x0e8b0afe,
0x973b7c8a,0xdbb52aa4,0x361cb5b8,0x0cea623c,0x0a39a0ca,0x1b7adef0,0xa84e8812,
0xb7c7df80,0x1e7f3edf,0x06a7d76e,0xceb2e5f1,0x77628fc5,0x46f7babd,0x95f9d749,
0x6b5bba8d,0x26372b85,0x73a0cfca,0x853876b1,0x771eee83,0x48f1535b,0xb5b4a4f3,
0xda7a8372,0xf3dcb3d9,0xa6470baa,0x39ee64bb,0xfc1a4d2b,0xb48e973c,0xc9a38a45,
0xdfafd948,0x52af9cac,0x16a659b5,0x37d7de53,0x9ff737b7,0xeececfba,0xcc201269,
0x19113d32,0xdac46991,0x8b92eefa,0x7489933c,0xa4e906fe,0x3f3128c8,0x53710666,
0xfa85e442,0x29243a81,0x23cea18c,0x341b017b,0x354330fa,0x06acc6a3,0xb5776960,
0xf7ffb9ca,0xc2af2563,0xc007ccab,0x2adfe3fd,0xab8d70dc,0x169c1f4a,0xa923b3eb,
0x4821833e,0xd156f0f8,0x3fafaffb,0x21dd460c,0x4b2f7fbc,0x5ea942a5,0x6ebc8b87,
0xd1e3a38b,0xe14779f0,0x7ca6a332,0x6d56e638,0xe55aa3fd,0xcb35545e,0xca7bd0d2,
0xb3e5d7fa,0xf8566a8b,0x81c34651,0x560d6a32,0x9a6981b4,0x4cab7124,0x072f0883,
0x3271a749,0x7b76cb66,0x5b8ab270,0x21698bf1,0xdbdddd47,0xa1a40cfd,0x4754b35a,
0xd4d5d31b,0xf12a4b1c,0x96a92984,0xde911f01,0x9f03276a,0x8d08891a,0x539183ad,
0xddbb6a2a,0x8ff41939,0x4670ba8e,0xe42bade5,0xd70899a5,0xd711d069,0x9e88ab3e,
0x9a62e276,0x57ca657d,0xea838f00,0xbc678507,0x3bafcad9,0x5fc4946f,0xac95b4f0,
0x0072cbd2,0x63493703,0xf860b2d2,0x56efc6b5,0xadcede5e,0x12f3bc72,0x495c7b0f,
0x52a438eb,0xb86dbb93,0xccc558d5,0xf48eeeee,0x48322eeb,0x6914523f,0xa28a7a31,
0x0202025f,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,
0x1ffe0202,0x4cd103fe,0x0000c90d,
};


#define BUFFER_SIZE 10000

char program_buffer[BUFFER_SIZE];    /* for uncompressed program */
char data_buffer[BUFFER_SIZE];       /* for compressed hex data */

 
int main(int argc, char *argv[]) {
  int i;
  z_stream strm;
  
  /* set up zlib to inflate compressed data into program buffer */
  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;
  inflateInit(&strm);
  strm.next_in = (Bytef *)COMPRESSED_DATA;
  strm.avail_in = sizeof(COMPRESSED_DATA);
  strm.next_out = program_buffer;
  strm.avail_out = BUFFER_SIZE;
  
  /* then actually inflate compressed data */
  inflate(&strm, Z_FINISH);
  
  /* Since global arrays are implicitly initialized to 0, data_buffer
   * is currently a zero-length string.
   * Expand compressed data to a hex array of ints, in data_buffer.
   */
  for (i = 0; i < sizeof(COMPRESSED_DATA)/sizeof(COMPRESSED_DATA[0]); ++i) {
    char temp_buffer[12];
    char newline[2] = "\n";
    
    /* writes to temp_buffer in the format of "0xffeeddcc," */
    sprintf(temp_buffer, "0x%08x,", COMPRESSED_DATA[i]);
    
    /* place an initial newline, followed by a newline every 80 characters */
    if (i%(80/11) == 0) {
      strcat(data_buffer, newline);
    }
    
    /* and write this int to the data buffer */
    strcat(data_buffer, temp_buffer);
  }
  
  /* now print out the program, including the hex data where the %s exists in
   * program_buffer
   */
  printf(program_buffer, data_buffer);
  
  return 0;
}


