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