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)