[comp.lang.c] Self-printing C program

meyer@unix.cis.pitt.edu (Timothy S. Meyer) (09/17/90)

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.

jeffj@mcs213j.cs.umr.edu (Jeff Jenness) (09/17/90)

In article <38724@unix.cis.pitt.edu> meyer@unix.cis.pitt.edu (Timothy S. Meyer) writes:
>
>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.

Here is an example of what you are looking for:

char p[]="char p[]=%c%s%c;main(){printf(p,34,p,34);}";main(){printf(p,34,p,34);}

Hope this helps,

-- 
Jeff Jenness
University of Missouri - Rolla
jeffj@cs.umr.edu

torbenm@gere.diku.dk (Torben [gidius Mogensen) (09/17/90)

meyer@unix.cis.pitt.edu (Timothy S. Meyer) writes:


>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.

I have several versions: one assume a maximum linelength of 80, the
other is a single long line.

------------------ max 80 ---------------------
char *a="\n\\\"char *a=%c%cn%c%c%s%c,*b=%.1s%c%s%c;%.1s%s%.1s",*b=
"main(){printf(a+3,a[2],a[1],a[1],a[1],a+1,a[2],a,a[2],b,a[2],a,b,a);}";
main(){printf(a+3,a[2],a[1],a[1],a[1],a+1,a[2],a,a[2],b,a[2],a,b,a);}
------------------ 1 line ---------------------
char *a="\\\"char *a=%c%.1s%.1s%.71s%.1sn%c;main(){printf(a+2,a[1],a,a,a,a,a[1]);}\n";main(){printf(a+2,a[1],a,a,a,a,a[1]);}
-----------------------------------------------

I also have Pascal programs:

------------------ max 80 ---------------------
program s(output);const a='program s(output);const a';b
=''';begin writeln(a,p,a,b:3);writeln(p,b:1,b,b:2);writeln(a:1,p,p,b:1,b)end.';
p='=''';begin writeln(a,p,a,b:3);writeln(p,b:1,b,b:2);writeln(a:1,p,p,b:1,b)end.
------------------ 1 line ---------------------
program s(output);const a=''';begin writeln(be,b,a:1,a,a:4,b,be,a:3,b,b,a:1,a)end.';be='program s(output);const a';b='=''';begin writeln(be,b,a:1,a,a:4,b,be,a:3,b,b,a:1,a)end.
-----------------------------------------------

You can make these shorter by omitting (output) in the heading, but
that will cause warnings when compiled.


Torben Mogensen (torbenm@diku.dk)

kdq@demott.COM (Kevin D. Quitt) (09/17/90)

In article <38724@unix.cis.pitt.edu> meyer@unix.cis.pitt.edu (Timothy S. Meyer) writes:
>
>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.


/*
This solution comes from the Winter 1989 edition EUUG newsletter. It appears
in Puzzle Corner edited by Mick Farmer (mick@cs.bbk.ac.uk). No author is
indicated.
*/
#define QUOTE '"'
#include <stdio.h>

int main()
{
 int i,j;
 extern char *s[];
 s[0][15] = QUOTE;
 for (i = 0; *s[i] != '$'; i++)
  puts(s[i]);
 s[0][15] = '$';
 for (j = 0; s[j]; j++) {
  putchar(QUOTE);
 fputs(s[j], stdout);
 putchar(QUOTE);
 putchar(',');
 puts(s[2]);
 }
 for (i++; s[i]; i++)
  puts(s[i]);
}

char *s[] = {
"#define QUOTE '$'",
"#include <stdio.h>",
"",
"int main()",
"{",
" int i,j;",
" extern char *s[];",
" s[0][15] = QUOTE;",
" for (i = 0; *s[i] != '$'; i++)",
"  puts(s[i]);",
" s[0][15] = '$';",
" for (j = 0; s[j]; j++) {",
"  putchar(QUOTE);",
" fputs(s[j], stdout);",
" putchar(QUOTE);",
" putchar(',');",
" puts(s[2]);",
" }",
" for (i++; s[i]; i++)",
"  puts(s[i]);",
"}",
"",
"char *s[] = {",
"$",
"NULL };",
NULL };


    Have fun!
-- 
 _
Kevin D. Quitt         demott!kdq   kdq@demott.com
DeMott Electronics Co. 14707 Keswick St.   Van Nuys, CA 91405-1266
VOICE (818) 988-4975   FAX (818) 997-1190  MODEM (818) 997-4496 PEP last

                96.37% of all statistics are made up.

djones@megatest.UUCP (Dave Jones) (09/19/90)

From article <38724@unix.cis.pitt.edu>, by meyer@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 == '\'');
    }
}