Self-printing C program

Dave Jones djones at megatest.UUCP
Wed Sep 19 08:35:54 AEST 1990


>From article <38724 at unix.cis.pitt.edu>, by meyer at unix.cis.pitt.edu (Timothy S. Meyer):
> 
> Seems to me I saw a self-printing C program a few years back in CACM or
> Computer magazine, but I can't seem to find it.  Can anyone give me a
> reference for such a program?  (A self-printing program is one that 
> outputs a copy of its own text and is more of a recreational interest I
> think.)
> 
> Any help will be appreciated.

There are lot's of versions around. Most of them are dependent on the
text-code (ASCII or EBCDIC), which I think blows the whole deal. Such
a program is a "C-and-ASCII" program, not a C program. Besides, the ones
I have seen are not very readable.

I wrote a machine-independent version a few years ago, just for the
heck of it. It bootstraps itself in a way that is both interesting and
instructional, I think.   Here 'tis. If you are interested in how it was
made, send me a note, and I'll send you are shar of the bootstrap procedure.
(I didn't write that insane string-constant by hand, I'll assure you.)

^^^^ snip ^^^^ snip ^^^^ snip ^^^^ snip ^^^^ snip ^^^^ snip ^^^^ snip
/* This program prints its source. */

main(argc, argv)
  char** argv;
{
  char * dna =

"/* This program prints its source. */\n\nmain(argc, argv)\n\
  char** argv;\n{\n  char * dna =\n\nZ;\n\n\n  express_stri\
ng(dna);\n  exit(0);\n}\n\n\n/* Express the string, substit\
uting a quotation of the string \n * for the character 'Z'.\
  Breaks the literal into lines of no\n * more than 60 char\
s.\n */\nexpress_string(str)\n  char* str;\n{\n  char* ptr \
= str;\n  char ch;\n  int is_quoted = 0;\n\n  while(ch = *p\
tr++)\n    {\n\n      if(ch == 'Z' && !is_quoted)\n\t{\n\t \
 int count = 1;\n\t  char* ptr = str;\n\t  char ch;\n\t  pu\
tchar('\"');\n\t  while(ch = *ptr++)\n\t    {\n\t      swit\
ch(ch)\n\t      {\n\t\tcase '\\n': printf(\"\\\\n\");  coun\
t +=2; break;\n\t\tcase '\\t': printf(\"\\\\t\");  count +=\
2; break;\n\t\tcase '\\\\': printf(\"\\\\\\\\\"); count +=2\
; break;\n\t\tcase '\"':  printf(\"\\\\\\\"\"); count +=2; \
break;\n\t\tdefault:   putchar(ch);    count +=1; break;\n\t\
      }\n\t      if(count >= 59)\n\t\t{ printf(\"\\\\\\n\")\
;\n\t\t  count = 0;\n\t\t}\n\t    }\n\t  putchar('\"');\n\t\
}\n\n      else putchar(ch);\n      is_quoted = ( ch == '\\\
'');\n    }\n}\n";


  express_string(dna);
  exit(0);
}


/* Express the string, substituting a quotation of the string 
 * for the character 'Z'.  Breaks the literal into lines of no
 * more than 60 chars.
 */
express_string(str)
  char* str;
{
  char* ptr = str;
  char ch;
  int is_quoted = 0;

  while(ch = *ptr++)
    {

      if(ch == 'Z' && !is_quoted)
	{
	  int count = 1;
	  char* ptr = str;
	  char ch;
	  putchar('"');
	  while(ch = *ptr++)
	    {
	      switch(ch)
	      {
		case '\n': printf("\\n");  count +=2; break;
		case '\t': printf("\\t");  count +=2; break;
		case '\\': printf("\\\\"); count +=2; break;
		case '"':  printf("\\\""); count +=2; break;
		default:   putchar(ch);    count +=1; break;
	      }
	      if(count >= 59)
		{ printf("\\\n");
		  count = 0;
		}
	    }
	  putchar('"');
	}

      else putchar(ch);
      is_quoted = ( ch == '\'');
    }
}



More information about the Comp.lang.c mailing list