allbery@ncoast.UUCP (05/18/87)
# An improved version of the self-replicating toy program. # # I won't bother you with this again, I promise. # # CUT HERE ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # # This is a shell-achive. # # UNPACKING INSTRUCTIONS # # 1. Remove everything above the "CUT HERE" line. # 2. Move the resulting text (this archive) to an empty directory. # 3. Change (cd) to that directory. # 4. If the name of this archive is also the name of one of the # archived files, change the name of this archive. # # The archived files are: # # selfrep.c # Makefile # buffered_file.c # express.c # conprog.c # soup.Z # # 5. Type "/bin/sh" followed by the archive name. Example: # # /bin/sh archive # #****************************************************************** if /bin/test -f selfrep.c then echo File \"selfrep.c\" already exists. Not overwritten. else # # echo x - selfrep.c sed 's/^XX//' > selfrep.c <<'@//E*O*F selfrep.c//' XX/* This program prints its source. */ XX XXmain(argc, argv) XX char** argv; XX{ XX char * dna = XX XX"/* This program prints its source. */\n\nmain(argc, argv)\n\ XX char** argv;\n{\n char * dna =\n\nZ;\n\n\n express(dna)\ XX;\n exit(0);\n}\n\n\n/* Express the string, substituting a\ XX quotation of the string \n** for the character 'Z'. Break\ XXs the literal into lines of no\n** more than 60 chars.\n*/\n\ XXexpress(str)\n char* str;\n{\n char* ptr = str;\n char c\ XXh;\n int is_quoted = 0;\n\n while(ch = *ptr++)\n {\n\n\ XX if(ch == 'Z' && !is_quoted)\n\t{\n\t int count = 1;\n\ XX\t char* ptr = str;\n\t char ch;\n\t putchar('\"');\n\t \ XX while(ch = *ptr++)\n\t {\n\t switch(ch)\n\t {\ XX\n\t case '\\n': printf(\"\\\\n\"); count +=2; break\ XX;\n\t\tcase '\\t': printf(\"\\\\t\"); count +=2; break;\n\t\ XX case '\\\\': printf(\"\\\\\\\\\"); count +=2; break\ XX;\n\t case '\"': printf(\"\\\\\\\"\"); count +=2; br\ XXeak;\n\t default: putchar(ch); count += 1; break;\n\t\ XX }\n\t if(count >= 59)\n\t\t{ printf(\"\\\\\\n\")\ XX;\n\t\t count = 0;\n\t\t}\n\t }\n\t putchar('\"');\n\t\ XX}\n\n else putchar(ch);\n is_quoted = ( ch == '\\\ XX'');\n }\n}\n"; XX XX XX express(dna); XX exit(0); XX} XX XX XX/* Express the string, substituting a quotation of the string XX** for the character 'Z'. Breaks the literal into lines of no XX** more than 60 chars. XX*/ XXexpress(str) XX char* str; XX{ XX char* ptr = str; XX char ch; XX int is_quoted = 0; XX XX while(ch = *ptr++) XX { XX XX if(ch == 'Z' && !is_quoted) XX { XX int count = 1; XX char* ptr = str; XX char ch; XX putchar('"'); XX while(ch = *ptr++) XX { XX switch(ch) XX { XX case '\n': printf("\\n"); count +=2; break; XX case '\t': printf("\\t"); count +=2; break; XX case '\\': printf("\\\\"); count +=2; break; XX case '"': printf("\\\""); count +=2; break; XX default: putchar(ch); count += 1; break; XX } XX if(count >= 59) XX { printf("\\\n"); XX count = 0; XX } XX } XX putchar('"'); XX } XX XX else putchar(ch); XX is_quoted = ( ch == '\''); XX } XX} @//E*O*F selfrep.c// fi if /bin/test -f Makefile then echo File \"Makefile\" already exists. Not overwritten. else # # echo x - Makefile sed 's/^XX//' > Makefile <<'@//E*O*F Makefile//' XX XXproof: selfrep XX selfrep > temp.c; diff temp.c selfrep.c; rm -f temp.c XX XXselfrep: selfrep.c XX cc selfrep.c -o selfrep XX XXselfrep.c: soup.Z conprog express.c XX /lib/cpp -P -C soup.Z > tempfile; conprog tempfile > selfrep.c; \ XX rm -f tempfile XX XXconprog: conprog.o express.o buffered_file.o XX cc conprog.o express.o buffered_file.o -o conprog XX XXclean: XX -rm -f selfrep selfrep.c conprog *.o @//E*O*F Makefile// fi if /bin/test -f buffered_file.c then echo File \"buffered_file.c\" already exists. Not overwritten. else # # echo x - buffered_file.c sed 's/^XX//' > buffered_file.c <<'@//E*O*F buffered_file.c//' XX#include <sys/param.h> XX#include <sys/file.h> XX#include <sys/dir.h> XX#include <sys/stat.h> XX#include <errno.h> XX XX/************************************************************************* XX** This procedure buffers up a named file, and returns a pointer to the XX** buffer. If something goes wrong, it returns NULL, and errno will have XX** been set. XX*/ XX XXchar* XXbuffered_file(file_name) XX char* file_name; XX XX{ XX XX char* file_buffer; XX struct stat stat_buf; XX int fd = open(file_name, O_RDONLY, 0); XX XX if (fd < 0 || fstat( fd, &stat_buf) == -1) XX return 0; XX XX file_buffer = (char*)malloc(stat_buf.st_size + 1); XX XX if(file_buffer == 0) XX return 0; XX XX if( read( fd, file_buffer, stat_buf.st_size ) != stat_buf.st_size ) XX { XX int error = errno; XX close(fd); XX free(file_buffer); XX errno = error; XX return 0; XX } XX XX file_buffer[stat_buf.st_size] = '\0'; XX XX close(fd); XX XX return file_buffer; XX XX} /* end.. buffered_file */ XX/****************************************************************************/ XX XX XX @//E*O*F buffered_file.c// fi if /bin/test -f express.c then echo File \"express.c\" already exists. Not overwritten. else # # echo x - express.c sed 's/^XX//' > express.c <<'@//E*O*F express.c//' XX/* Express the string, substituting a quotation of the string XX** for the character 'Z'. Breaks the literal into lines of no XX** more than 60 chars. XX*/ XXexpress(str) XX char* str; XX{ XX char* ptr = str; XX char ch; XX int is_quoted = 0; XX XX while(ch = *ptr++) XX { XX XX if(ch == 'Z' && !is_quoted) XX { XX int count = 1; XX char* ptr = str; XX char ch; XX putchar('"'); XX while(ch = *ptr++) XX { XX switch(ch) XX { XX case '\n': printf("\\n"); count +=2; break; XX case '\t': printf("\\t"); count +=2; break; XX case '\\': printf("\\\\"); count +=2; break; XX case '"': printf("\\\""); count +=2; break; XX default: putchar(ch); count += 1; break; XX } XX if(count >= 59) XX { printf("\\\n"); XX count = 0; XX } XX } XX putchar('"'); XX } XX XX else putchar(ch); XX is_quoted = ( ch == '\''); XX } XX} @//E*O*F express.c// fi if /bin/test -f conprog.c then echo File \"conprog.c\" already exists. Not overwritten. else # # echo x - conprog.c sed 's/^XX//' > conprog.c <<'@//E*O*F conprog.c//' XX XXmain(argc, argv) XX char** argv; XX{ XX express(buffered_file(argv[1])); XX exit(0); XX} @//E*O*F conprog.c// fi if /bin/test -f soup.Z then echo File \"soup.Z\" already exists. Not overwritten. else # # echo x - soup.Z sed 's/^XX//' > soup.Z <<'@//E*O*F soup.Z//' XX/* This program prints its source. */ XX XXmain(argc, argv) XX char** argv; XX{ XX char * dna = XX XXZ; XX XX XX express(dna); XX exit(0); XX} XX XX#include "express.c" @//E*O*F soup.Z// fi echo finished # # END OF ARCHIVE -- Brandon S. Allbery {decvax,cbatt,cbosgd}!cwruecmp!ncoast!allbery Tridelta Industries {ames,mit-eddie,talcott}!necntc!ncoast!allbery 7350 Corporate Blvd. necntc!ncoast!allbery@harvard.HARVARD.EDU Mentor, OH 44060 +01 216 255 1080 (also eddie.MIT.EDU)