#include <stdio.h>

/* This program is a self-replicating program.  In other words, it
 * will print its own listing.  There are many such programs.  This
 * one, however, was designed in order to be elegant, portable, and
 * devoid of dirty hacks. */

/* The following characters must be quoted in a string. */
const char quote = '"';
const char escape = '\\';

/* Strings respectively prepended and appended before a quoted
 * string. */
const char *qline1 = "  \"";
const char *qline2 = "\",\n";

void
printquoted (const char *s)
     /* Quote print a character string. */
{
  int i;

  printf ("%s", qline1);
  for ( i=0 ; s[i] ; i++ )
    {
      if ( ( s[i] == quote ) || ( s[i] == escape ) )
	printf ("%c", escape);
      printf ("%c", s[i]);
    }
  printf ("%s", qline2);
}

void
quine (const char *tab[], const char *middle)
     /* The Quine operation: this function prints the first part of
      * the tab board (up to NULL), then prints it again quoted, the
      * prints the middle part, then the second part quoted, and
      * finally the second part unquoted. */
{
  int i,j;

  for ( i=0 ; tab[i] ; i++ )
    printf ("%s\n", tab[i]);
  for ( j=0 ; tab[j] ; j++ )
    printquoted (tab[j]);
  printf ("%s\n", middle);
  for ( j++ ; tab[j] ; j++ )
    printquoted (tab[j]);
  for ( i++ ; tab[i] ; i++)
    printf ("%s\n", tab[i]);
}

/* The string to be printed in the "middle", between the first and
 * second parts. */
const char *middle = "  NULL, /* And now the \"second\" part */";

const char *tab[] = {
  "#include <stdio.h>",
  "",
  "/* This program is a self-replicating program.  In other words, it",
  " * will print its own listing.  There are many such programs.  This",
  " * one, however, was designed in order to be elegant, portable, and",
  " * devoid of dirty hacks. */",
  "",
  "/* The following characters must be quoted in a string. */",
  "const char quote = '\"';",
  "const char escape = '\\\\';",
  "",
  "/* Strings respectively prepended and appended before a quoted",
  " * string. */",
  "const char *qline1 = \"  \\\"\";",
  "const char *qline2 = \"\\\",\\n\";",
  "",
  "void",
  "printquoted (const char *s)",
  "     /* Quote print a character string. */",
  "{",
  "  int i;",
  "",
  "  printf (\"%s\", qline1);",
  "  for ( i=0 ; s[i] ; i++ )",
  "    {",
  "      if ( ( s[i] == quote ) || ( s[i] == escape ) )",
  "	printf (\"%c\", escape);",
  "      printf (\"%c\", s[i]);",
  "    }",
  "  printf (\"%s\", qline2);",
  "}",
  "",
  "void",
  "quine (const char *tab[], const char *middle)",
  "     /* The Quine operation: this function prints the first part of",
  "      * the tab board (up to NULL), then prints it again quoted, the",
  "      * prints the middle part, then the second part quoted, and",
  "      * finally the second part unquoted. */",
  "{",
  "  int i,j;",
  "",
  "  for ( i=0 ; tab[i] ; i++ )",
  "    printf (\"%s\\n\", tab[i]);",
  "  for ( j=0 ; tab[j] ; j++ )",
  "    printquoted (tab[j]);",
  "  printf (\"%s\\n\", middle);",
  "  for ( j++ ; tab[j] ; j++ )",
  "    printquoted (tab[j]);",
  "  for ( i++ ; tab[i] ; i++)",
  "    printf (\"%s\\n\", tab[i]);",
  "}",
  "",
  "/* The string to be printed in the \"middle\", between the first and",
  " * second parts. */",
  "const char *middle = \"  NULL, /* And now the \\\"second\\\" part */\";",
  "",
  "const char *tab[] = {",
  NULL, /* And now the "second" part */
  "  NULL",
  "};",
  "",
  "int",
  "main (void)",
  "{",
  "  quine (tab, middle);",
  "  return 0;",
  "}",
  NULL
};

int
main (void)
{
  quine (tab, middle);
  return 0;
}
