Xref: utzoo comp.lang.misc:5486 comp.lang.c:31946 Path: utzoo!attcan!uunet!decwrl!megatest!djones From: djones@megatest.UUCP (Dave Jones) Newsgroups: comp.lang.misc,comp.lang.c Subject: Re: Self-printing C program Message-ID: <13927@goofy.megatest.UUCP> Date: 18 Sep 90 22:35:54 GMT References: <38724@unix.cis.pitt.edu> Organization: Megatest Corporation, San Jose, Ca Lines: 97 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 == '\''); } }