[comp.sources.misc] self-replicating toy program

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)