From: chongo@hoptoad.uucp (Landon C. Noll)
Newsgroups: comp.lang.c,comp.sources.d,comp.unix.wizards,alt.sources,misc.misc
Subject: 1992 International Obfuscated C Code Contest winners, 2 of 4
Keywords: ioccc
Date: 9 Sep 92 01:40:13 GMT
Expires: 28 Nov 92 00:00:00 GMT
Reply-To: chongo@hoptoad.UUCP (Landon C. Noll)
Organization: Nebula Consultants in San Francisco

Submitted-by: chongo@toad.com (Landon Curt Noll)
#
# Send comments, questions, bugs to: 
#
#    judges@toad.com   -or-   ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
#
# You are strongly encouraged to read the new contest rules before
# sending any entries.  The rules, and sometimes the contest Email
# address itself, change over time.  A valid entry one year may
# be rejected in a later year due to changes in the rules.  The typical
# start date for a contest is early March.  The typical end date for a
# contest is early May.
#
# The contest rules are posted to comp.unix.wizards, comp.lang.c,
# misc.misc, alt.sources and comp.sources.d.  If you do not have access 
# to these groups, or if you missed the early March posting, you may 
# request a copy from the judges, via Email, at the address above.
#
Archive-name: ioccc.1992/part02

---- Cut Here and unpack ----
#!/bin/sh
# This is part 02 of ioccc.1992
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= 1992/albert.c ==============
echo "x - extracting 1992/albert.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/albert.c &&
X#include <stdio.h>
X#include <malloc.h>
X#include <setjmp.h>
X#include <ctype.h>
X#define new(PP) (PP *) malloc(sizeof(PP)) 
Xtypedef struct q {
X    jmp_buf ppp;
X    long qq;
X    struct q *P;
X    struct q *p;
X} 
XPP;
X
XPP *P;
Xint aaaaaa=2;
Xint aaaaaaa=1;
X
Xlong qqq;
X
X
XaaAaaa(aa,aaa)
Xchar *aa;
Xchar *aaa;
X{
X    char aaaa = 0;
X    if ((((( aaa )))))
X    {
X        aaaa = *aa;
X        *aa=0;
X        aa+=strlen(aa+1);
X        P =new(PP);
X        P->P=P;
X        P->p=P;
X    }
X
X    if ((((( !setjmp(P->ppp) ))))) 
X        {
X        if ((((( !isdigit(*aa) )))))
X            longjmp(P->ppp,aaaaaaa);
X        else {
X            P->p->P = new(PP);
X            P->p->P->P = P;
X            P->p->P->p = P->p;
X            P->p = P->p->P;
X
X            P->qq = *aa--;
X            P = P->p;
X            aaAaaa(aa,0);
X        }
X    } else {
X        if ( !aaaa&&!*aa ) 
X           longjmp(P->p->ppp,aaaaaaa);
X
X        if ((((( (P->qq=aaaa)<10     &&!
X                 (isdigit(aaaa))     ||!
X                 (isdigit(*aa)       ||!
X                 *aa                        )))))) 
X        {
X            fprintf(stderr,"Usage %c%s <number>\n",
X            (aaa[0]?7:aaaa),aaa+!aaa[0]);
X            exit(1);
X        }
X    }
X}
X
X
XppPppp(pp,ppp)
XPP **pp, *ppp;
X{
X    int aa;
X    if ((((( !(aa=setjmp(ppp->ppp))||aa==aaaaaa )))))
X    {
X        if ((((( *pp==ppp )))))
X        {
X            ppp = (*pp)->p;
X
X            if ( qqq<47 ) return;
X            if ( ppp->qq!=48 ) return;
X
X            while ( ppp->qq==48 ) 
X            {
X                printf("%ld\n",qqq-45);
X                *pp = ppp;
X                ppp = ppp->p;
X            }
X            qqq -= 1;
X            longjmp(ppp->ppp,aaaaaaa);
X        } else {
X            PP *p;
X
X            ppPppp(pp,ppp->p);
X            for (p=ppp;p!=*pp;p=p->p)
X            {
X                int qq=4;
X                if ((((( qqq<47                            &&
X                         (qq=0,p->qq+=p->p->qq-96)>=48-qqq ||
X                         qqq>46                            &&
X                         (p->qq-=p->p->qq)<0                   ))))) 
X                {
X                    p->qq += qqq+qq;
X                    if ( p->p==P && qqq<=46 )
X                    {
X                        P->p->P = new(PP);
X                        P->p->P->P = P;
X                        P->p->P->p = P->p;
X                        *pp = P = P->p = P->p->P;
X                        P->qq = 48;
X                    }
X
X                    p->p->qq+=qq==0;
X                    p->p->qq-=qq!=0;
X                }
X                else
X                {
X                    p->qq += 48;
X                }
X            }
X            if ( ppp->P==P ) longjmp(ppp->ppp,aaaaaaa);
X        }
X    }
X    else
X    {
X        qqq += 1; 
X
X        while (48==P->qq )
X        {
X            P->P->p = P->p;
X            P = P->p->P = P->P;
X
X        }
X
X        if ( ppp!=ppp->p->p || qqq<47 )
X            longjmp(ppp->ppp,aaaaaa);
X        else
X        {
X            printf("At most one remains\n");
X            exit(0);
X        }
X    }
X}
X
X
Xmain(aaa,aaaa)
Xint aaa;
Xchar **aaaa;
X{
X    aaAaaa(aaa==aaaaaaa?aaaa[0]:aaaa[1],aaaa[0]);
X    qqq = 39;
X    ppPppp(&P,P->p);
X}
X
X
SHAR_EOF
$TOUCH -am 0817110092 1992/albert.c &&
chmod 0444 1992/albert.c ||
echo "restore of 1992/albert.c failed"
set `wc -c 1992/albert.c`;Wc_c=$1
if test "$Wc_c" != "3164"; then
	echo original size 3164, current size $Wc_c
fi
# ============= 1992/albert.hint ==============
echo "x - extracting 1992/albert.hint (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/albert.hint &&
XMost Useful Program: <albert%bsovax@sun4nl.nluug.nl> Albert van der Horst
X
X	Albert van der Horst
X	S P&A R&C
X	Oranjestraat 8
X	3511 RA   UTRECHT
X	The Netherlands
X
X
XJudges' comments:
X
X    For a canned example:
X	make albert
X	albert 1234567890123456789
X    
X    We were impressed with the speed at which it was able to factor
X    arbitrarily large numbers consisting of factors that fit into
X    a long.
X
X
XSelected notes from the author:
X
X    The Obfuscated version of the Horst algorithm.
X
X    This program will factor unlimited length numbers and print the 
X    factors in ascending order. Numbers of one digit (e.g. 8) 
X    are rejected without notice.
X    It quits as soon as there is at most one
X    factor left, but that factor will not be shown. 
X    It accomplishes this efficiently, without resorting to division
X    or multiplication, until the candidate factor no longer fits in 
X    a signed long. 
X
X    The nicest way is to rename the program into e.g. 4294967297
X    if you want to factor Fermat's 4th number. Then just run it.
X    Or you may type "prog <some-number>"
X    A nice one is also (30 ones)
X    albert 111111111111111111111111111111
X
X    Apart from the foregoing there are no special execution instructions.
X
X    To customize the program into a factorizer of a fixed number, use
X    cc albert.c -o 4294967297
X    or some such.
X
X    There are no data files used, and it is not possible to feed input
X    via stdin.
X
X    I think this program is a nice example of algorithmic obfuscation.
X    Several times two similar algorithms are merged into one. Then you 
X    need quite some tricks to get it running, such as long jumps 
X    through recursive subroutines. I felt like a sword smith, 
X    welding the sword very long, folding it again to the proper 
X    length, keep on hammering till it is tight, then fold again.
X    Always keeping it at the proper red hot temperature, but not too
X    hot lest the hardness fades.
X    The strict naming conventions for subroutines did not make things 
X    much clearer after all, but it was not supposed to.
X
X    I would like to draw attention to the robustness of the program
X    with respect to error handling and the nice stopping criterion.
X    The esthetic appeal of some lines is at the expense of clearness, 
X    I apologize.
X    Running the program through the c-beautifier reveals nothing,
X    it will only destroy some of the lay out.
X    Running the program through lint shows the usual remarks for a
X    K&R program. Defeating this through casts does not make a program 
X    cleaner in my opinion.
X
X    Here are some hints, but they may not be too helpful.
X    1. The Horst algorithm is described in the Hobby Computer Club 
X	Newsletter, year 82, part 4, a real Dutch treat.
X       Assembler, c and Forth version have been around for some years.
X    2. Does fractal programming exist after all?
X    3. You remember the ToomCook algorithm in Knuth?
X       It uses iteration instead of recursion and is quite jumpy.
X       This program shares these disadvantages in a modified form.
X    4. The Conversion is to be found in Knuth, not so the Observation.
X       The Observation: "if it ends in a zero, it is divisible by ten"
SHAR_EOF
$TOUCH -am 0908160292 1992/albert.hint &&
chmod 0444 1992/albert.hint ||
echo "restore of 1992/albert.hint failed"
set `wc -c 1992/albert.hint`;Wc_c=$1
if test "$Wc_c" != "3193"; then
	echo original size 3193, current size $Wc_c
fi
# ============= 1992/albert.orig.c ==============
echo "x - extracting 1992/albert.orig.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/albert.orig.c &&
X#include <stdio.h>
X#include <malloc.h>
X#include <setjmp.h>
X#include <ctype.h>
X#define new(PP) (PP *) malloc(sizeof(PP)) 
Xtypedef struct q {
X    jmp_buf ppp;
X    long qq;
X    struct q *P;
X    struct q *p;
X} 
XPP;
X
XPP *P;
Xint aaaaaa=2;
Xint aaaaaaa=1;
X
Xlong qqq;
X
X
XaaAaaa(aa,aaa)
Xchar *aa;
Xchar *aaa;
X{
X    char aaaa = 0;
X    if ((((( aaa )))))
X    {
X        aaaa = *aa;
X        *aa=0;
X        aa+=strlen(aa+1);
X        P =new(PP);
X        P->P=P;
X        P->p=P;
X    }
X
X    if ((((( !setjmp(P->ppp) ))))) 
X        {
X        if ((((( !isdigit(*aa) )))))
X            longjmp(P->ppp,aaaaaaa);
X        else {
X            P->p->P = new(PP);
X            P->p->P->P = P;
X            P->p->P->p = P->p;
X            P->p = P->p->P;
X
X            P->qq = *aa--;
X            P = P->p;
X            aaAaaa(aa,0);
X        }
X    } else {
X        if ( !aaaa&&!*aa ) 
X           longjmp(P->p->ppp,aaaaaaa);
X
X        if ((((( (P->qq=aaaa)<10     &&!
X                 (isdigit(aaaa))     ||!
X                 (isdigit(*aa)       ||!
X                 *aa                        )))))) 
X        {
X            fprintf(stderr,"Usage %c%s <number>\n",
X            (aaa[0]?7:aaaa),aaa+!aaa[0]);
X            exit(1);
X        }
X    }
X}
X
X
XppPppp(pp,ppp)
XPP **pp, *ppp;
X{
X    int aa;
X    if ((((( !(aa=setjmp(ppp->ppp))||aa==aaaaaa )))))
X    {
X        if ((((( *pp==ppp )))))
X        {
X            ppp = (*pp)->p;
X
X            if ( qqq<47 ) return;
X            if ( ppp->qq!=48 ) return;
X
X            while ( ppp->qq==48 ) 
X            {
X                printf("%ld\n",qqq-45);
X                *pp = ppp;
X                ppp = ppp->p;
X            }
X            qqq -= 1;
X            longjmp(ppp->ppp,aaaaaaa);
X        } else {
X            PP *p;
X
X            ppPppp(pp,ppp->p);
X            for (p=ppp;p!=*pp;p=p->p)
X            {
X                int qq=4;
X                if ((((( qqq<47                            &&
X                         (qq=0,p->qq+=p->p->qq-96)>=48-qqq ||
X                         qqq>46                            &&
X                         (p->qq-=p->p->qq)<0                   ))))) 
X                {
X                    p->qq += qqq+qq;
X                    if ( p->p==P && qqq<=46 )
X                    {
X                        P->p->P = new(PP);
X                        P->p->P->P = P;
X                        P->p->P->p = P->p;
X                        *pp = P = P->p = P->p->P;
X                        P->qq = 48;
X                    }
X
X                    p->p->qq+=qq==0;
X                    p->p->qq-=qq!=0;
X                }
X                else
X                {
X                    p->qq += 48;
X                }
X            }
X            if ( ppp->P==P ) longjmp(ppp->ppp,aaaaaaa);
X        }
X    }
X    else
X    {
X        qqq += 1; 
X
X        while (48==P->qq )
X        {
X            P->P->p = P->p;
X            P = P->p->P = P->P;
X
X        }
X
X        if (ppp!=ppp->p->p )
X            longjmp(ppp->ppp,aaaaaa);
X        else
X        {
X            printf("At most one remains\n");
X            exit(0);
X        }
X    }
X}
X
X
Xmain(aaa,aaaa)
Xint aaa;
Xchar **aaaa;
X{
X    aaAaaa(aaa==aaaaaaa?aaaa[0]:aaaa[1],aaaa[0]);
X    qqq = 39;
X    ppPppp(&P,P->p);
X}
X
X
SHAR_EOF
$TOUCH -am 0817110092 1992/albert.orig.c &&
chmod 0444 1992/albert.orig.c ||
echo "restore of 1992/albert.orig.c failed"
set `wc -c 1992/albert.orig.c`;Wc_c=$1
if test "$Wc_c" != "3153"; then
	echo original size 3153, current size $Wc_c
fi
# ============= 1992/ant.README ==============
echo "x - extracting 1992/ant.README (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/ant.README &&
XNAME
X
X	am		Anthony's Make 
X
X
XSYNOPSIS
X
X	am <makefile> [target]
X
X
XDESCRIPTION
X
XAM is a programmer's tool to maintain, update, and regenerate groups
Xof files and/or programs.  It is similar to MAKE as described by the
XPOSIX.2 draft standard 11.2, and this document parallels the draft
Xin order to point out the subtle differences between AM and MAKE.
X
XThe AM utility can be used as part of software development to update
Xfiles that are derived from other files.  A typical case is one where
Xobject files are derived from the corresponding source files.  The AM
Xutility examines time relationships and updates those derived files
X(targets) that have modified times earlier than the modified times of
Xthe files (prerequisites) from which they are derived.  A description 
Xfile ("makefile") contains a description of the relationships between 
Xfiles, and the commands that must be executed to update the targets to
Xreflect changes in their prerequisites.  Each specification, or rule, 
Xshall consist of a target, optional prerequisites, and optional 
Xcommands to be executed when a prerequisite is newer than the target.
X
X
XOPTIONS
X
XNone.
X
X
XOPERANDS
X
Xmakefile	This required argument, is a pathname of a description
X		file, which is also referred to as the "makfile".  A
X		pathname of "-", shall *NOT* denote the standard input.
X
Xtarget		This optional argument, is the first target to be 
X		processed.  If no target is specified, when AM is
X		processing the makefile, the first target that AM
X		encounters shall be used.
X
X
XEXTERNAL INFLUENCES
X
XSTANDARD INPUT
X
XNot used.
X
X
XINPUT FILES
X
XThe input file, otherwise known as the makefile, is a text file
Xcontaining rules, macro definitions, and comments.
X
X
XASYNCHRONOUS EVENTS
X
XAll traps are left to their default actions.  If AM receives a SIGHUP,
XSIGTERM, SIGINT, or SIGQUIT then AM will terminate as per request
X*WITHOUT* removing the current target.
X
X
XEXTERNAL EFFECTS
X
XSTANDARD OUTPUT
X
XThe AM utility shall write all commands to be executed to standard
Xoutput unless the command is prefixed with an at-sign (@).  If AM is
Xinvoked without any work needing to be done, it shall *NOT* write a
Xmessage to standard output indicating that no action was taken. 
X
X
XSTANDARD ERROR
X
XStandard error is used for diagnostic messages only.
X
X
XOUTPUT FILES
X
XNone.  However, the utilities invoked by AM may create additional files.
X
X
XEXTENDED DESCRIPTION
X
XThe AM utility attempts to perform the actions required to ensure
Xthat the specified target(s) are up-to-date.  A target is considered
Xout-of-date if it is older than any of its prerequisites or it does
Xnot exist.  The AM utility shall treat all prerequisites as targets
Xthemselves and recursively ensure that they are up-to-date, processing
Xthem in the order which they appear in the rule.  The AM utility shall
Xuse the modification times of files to determine if the corresponding
Xtargets are out-of-date.
X
XAfter AM has ensured that all of the prerequisites of a target are
Xup-to-date, and if the target is out-of-date, the commands associated
Xwith the target entry shall be executed.  If there are no commands
Xlisted for the target, the target shall be treated as up-to-date.
X
X
XMAKEFILE SYNTAX
X
XA makefile can contain rules, macro definitions, and comments.  If a
Xmacro is defined more than once, the value of the macro shall be the
Xlast one specified.  Comments start with a number-sign (#) and
Xcontinue until an unescaped <newline> is reached.
X
XA backslash before a <newline> serves as a line continuation mark, and 
Xis used to create long-lines.   A line will continue to be extended until 
Xan unescaped <newline> is reached.
X
XWhen an escaped <newline> (one preceded by a backslash) is found anywhere
Xin the makefile, it shall be replaced, along with any leading white 
Xspace on the following line, with a single <space>.  
X
X
XMAKEFILE EXECUTION
X
XCommand lines shall be processed one at a time by writing the command
Xline to standard output, unless prefixed with an at-sign (@), and
Xexecuting the command(s) in the line.  Commands shall be executed by
Xpassing the command line to the command interpreter via the system()
Xfunction.
X
XThe environment for the command being executed shall contain all of the
Xvariables in the environment of AM.  All macros are considered to be part 
Xof the environment too.
X
XBy default, when AM receives a non-zero status from the execution of a
Xcommand, it terminates with an error message to standard error.  If
Xthe command is prefixed by a hyphen (-) then any error found while
Xexecuting the command shall be ignored.
X
XCommand lines can have one or more of the following prefixes: a hyphen
X(-) to ignore errors, an at-sign (@) to be silent, or a plus-sign (+)
Xif the command is always executed (this prefix is for compatibility with
XMAKE and is ignored).
X
X
XTARGET RULES
X
XTarget rules are formatted as follows:
X
X	target [target ...] : [prerequisite ...]
X	[<tab>command
X	 <tab>command
X	 ...]
X
X	(line that does not begin with <tab>)
X
XTarget entries are specified by a <blank>-separated, non-null list of
Xtargets, then a colon, then a <blank>-separated, possibly empty list
Xof prerequisite.  All following lines, if any, that begin with a <tab>,
Xare command lines to be executed to update the target(s).  The first
Xline that does not begin with a <tab> shall begin a new entry.
X
XTarget names can be any character supported by the host system,
Xexcluding <blank>s, <tab>s, <newline>s, and colons (:), which are used 
Xfor delimiters.
X
XFor any given target there can be only one target rule.  The first
Xoccurrence of a target in a makefile shall be used.  All subsequent
Xrules for the same target are ignored.  There is *no* support for 
Xadding prerequisites to a target's prerequisite list once a target
Xrule is defined.
X
XThere are no special targets or inference rule support.  
X
X
XMACROS
X
XMacro definitions are in the form:
X
X	string1 = [string2]
X
XThe macro named string1 is defined as having the value of string2,
Xwhere string2 is defined as all characters, if any, after the equal
Xsign up to an unescaped <newline>.  Any <blank>s immediately before or
Xafter the equal sign shall be ignored.
X
XSubsequent appearances of $(string1) shall be replaced by string2.
XThe parentheses are *NOT* optional if string1 is a single character.
XThe macro $$ shall be replaced by the single character $.  
X
XMacro names can be any character that the host system would allow in 
Xthe definition of environment variables, excluding parentheses, ( and ), 
Xwhich are used for delimiters.
X
XMacros can appear anywhere in the makefile, except within other macro 
Xreferences (ie. no nesting).  Macros in target and command lines shall 
Xbe evaluated when the line is read.  Macros in macro definition lines 
Xshall be evaluated *IMMEDIATELY*.  A macro that has not been defined 
Xshall evaluate to a null string without causing any error condition.  
X
XIf a macro is defined more than once, the value of the macro shall be the 
Xlast one specified prior to it being referenced.
X
XMacro assignments shall be accepted from the sources listed below, in 
Xthe order shown.  If a macro name already exists at the time it is being
Xprocessed, the newer definition shall replace the existing definition.
X
X   1)	The contents of the environment, including the variables with
X	null values in the order defined in the environment.
X
X   2)	Macros defined in the makefile, processed in the order specified.
X
XThere are no internal macros supported.  The SHELL macro shall *NOT* be
Xtreated specially.
X
X
XEXIT STATUS
X
X  0	Successful completion.
X  1	General error.
X  2	Usage error.
X  3	Failed to open makefile.
X  4	Failed to allocate memory.
X
X
XINSTALLATION
X
XAM can be built on any system providing at least K&R C.  It has been 
Xtested on 
X
X	o  SunOS with GCC
X	o  ATARI Mega ST with Sozobon C
X	o  PC clone with Turbo C
X	o  Interactive UNIX System V/386 release 3.2
X
XFor all machines, the compile command line should be
X
X	cc -O -o am am.c
X
XThe value RULES represents the number of slots available to record
Xtarget rules, dependencies, and commands.  The default value chosen
Xshould handle most project makefiles.  RULES can be overridden on the
Xcommand line with -DRULES=nn, where 0 < nn < INT_MAX.
X
XOn a DOS machine using Turbo C, it may be necessary to add the include
Xdirective
X
X	#include <time.h>
X
Xwith the rest of the includes if sys/stat.h does not properly define or
Xuse time_t.  Also, on some older K&R C compilers, stdlib.h may not be 
Xdefined and so it might be necessary to remove the include directive for 
Xit. 
X
X
XREFERENCES
X
X[Mil87]	Webb Miller, "A Software Tools Sampler", Prentice Hall, 87
X	ISBN 0-13-822305-X, chaper 2
X
X[POSIX]	POSIX.2 draft 11.2 MAKE
X
X
XFILES
X
Xant.c		Obfuscated source
Xant.README	Manual for AM
Xant.test.mk	Test makefile
X
X
XBUGS
X
XUnknown as of 20 March 92.
SHAR_EOF
$TOUCH -am 0817110092 1992/ant.README &&
chmod 0400 1992/ant.README ||
echo "restore of 1992/ant.README failed"
set `wc -c 1992/ant.README`;Wc_c=$1
if test "$Wc_c" != "8745"; then
	echo original size 8745, current size $Wc_c
fi
# ============= 1992/ant.c ==============
echo "x - extracting 1992/ant.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/ant.c &&
X#define W while
X#define S strspn 
X#define R return 
X#define F fprintf(stderr,
X#define C continue;
X
X#include <stdlib.h>
X#include <stdio.h>
X#include <string.h>
X#include <sys/stat.h>
X
X#ifndef RULES
X#define RULES	500
X#endif
X
X#define N(p, i)	(p += i, p += S(p, w), i = strcspn(p, w))
X
Xchar *b, l[BUFSIZ], *t[RULES], *d[RULES], *c[RULES], w[] = "\n\t ";
X
Xtime_t M();
Xint T();
Xvoid U();
X
X
Xtime_t
XM(f)
Xchar *f;
X{
X	int j, x;
X	size_t i = 0;
X	struct stat s;
X	N(f, i);
X	x = f[i];
X	f[i] = 0; 
X	j = stat(f, &s);
X	f[i] = x;
X	R j < 0 ? 0 : s.st_mtime;
X}
X
Xint
XT(f)
Xchar *f;
X{
X	char *q;
X	size_t i = 0, j, k = 1;
X	N(f, i);
X	W ((q = t[k])) {
X		j = 0;
X		W (N(q, j)) {
X			if (i == j && !strncmp(f, q, i))
X				R k;
X		}
X		++k;
X	}
X	R 0;
X}
X
Xvoid
XU(f)
Xchar *f;
X{
X	time_t t = M(f);
X	size_t i = 0, j = !t, k = T(f);
X	char *p = d[k], *q = c[k];
X	if (!N(p, i) && q && *q != '\t' && j) {
X		F "am: Don't know how to make '%s'.\n", f);
X		exit(1);
X	}
X	W (0 < i) {
X		U(p);
X		if (t < M(p))
X			j = 1;
X		N(p, i);
X	}
X	if (j && q && *q == '\t') {
X		sleep(1);
X		W (*q++ == '\t') {
X			i = j = 1;
X			W (0 < S(q, "-+@")) {
X				if (*q == '@')
X					
X					i = 0;
X				if (*q++ == '-')
X					
X					j = 0;
X			}
X			if (i)
X				puts(q);
X			if (system(q) && j) {
X				F "am: Error making '%s'\n", f);
X				exit(1);
X			}
X			q += strlen(q) + 1;
X		}
X		c[k] = 0;
X	}
X}
X
Xint
Xmain(u, v)
Xint u;
Xchar **v;
X{
X	FILE *f;
X	struct stat s;
X	size_t i, j, k;
X	char *m, *n, *p, *q, *r;
X	if (u < 2) {
X		F "usage: am <makefile> [target]\n");
X		R 2;
X	}
X	if (stat(*++v, &s) || !(f = fopen(*v, "r")))
X		R 3;
X	q = b = malloc(2*s.st_size);
X	if (!b)
X		R 4;
X	i = 1;
X	k = 0;
X	m = 0;
X	*t = *d = *c = "";
X	W ((r = fgets(l, BUFSIZ, f))) {
X		if (RULES <= i) {
X			F "am: Number of target-rules exceeds %d.\n", RULES);
X			R 1;
X		}
X		if (k) {
X			*q++ = ' ';
X			r += S(r, w);
X		} else {
X			if (t[i])
X				c[i++] = q;
X			if (m && putenv(m))
X				F "am: No more environment space.\n");
X			m = 0;
X			if (*l == '#' || *l == '\n')
X				C
X			p = q;
X		}
X		W (!(k = *r == '\\' && r[1] == '\n') && *r) {
X			if (*r == '$') {
X				if (r[1] == '(') {
X					n = r+2;
X					r += strcspn(r, ")");
X					*r++ = 0;
X					n = getenv(n);
X					if (n) 
X						q = strcpy(q, n) + strlen(n);
X					C
X				}
X				if (*r == r[1])
X					++r;
X			} 
X			if (*r == '=' && *l != '\t' && !m) {
X				*q = 0;
X				m = p;
X				j = 0;
X				q = N(m, j) + m;
X				*q++ = *r;
X				j = 1;
X				if (!N(r, j))
X					*q++ = 0;
X				C
X			}
X			if (*r == ':') {
X				t[i] = p;
X				*r = 0;
X				d[i] = q+1;
X			}
X			if (*r == '\n')
X				*r = 0;
X			*q++ = *r++;
X		}
X	}
X	fclose(f);
X	U(2 < u ? *++v : t[1]);
X	R 0;
X}
X
SHAR_EOF
$TOUCH -am 0817110092 1992/ant.c &&
chmod 0444 1992/ant.c ||
echo "restore of 1992/ant.c failed"
set `wc -c 1992/ant.c`;Wc_c=$1
if test "$Wc_c" != "2547"; then
	echo original size 2547, current size $Wc_c
fi
# ============= 1992/ant.hint ==============
echo "x - extracting 1992/ant.hint (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/ant.hint &&
XBest Utility: <ant@mks.com> Anthony C Howe
X
X	Anthony C Howe
X	Mortice Kern Systems Inc.
X	Unit 1, 14 Weber Street North
X	Waterloo, Ontario
X	N2J 3G4
X	Canada
X
X
XJudges' comments:
X
X   To use:
X	make am
X	am ant.test.mk
X    
X    Like much of Posix, obfuscation has its place.  Your task is to
X    figure out where.
X
X    This entry comes complete with a Posix-like command description.
X    Interested Posix balloters should lobby the IEEE for an obfuscated 
X    P1003 sub-committee.
X
X    We also suggest that you try:
X	make am
X	am Makefile am_clobber		<-- clobber everything except am
X	am Makefile all
X
X
XSelected notes from the author:
X
X    See the file ant.README.
SHAR_EOF
$TOUCH -am 0908160292 1992/ant.hint &&
chmod 0444 1992/ant.hint ||
echo "restore of 1992/ant.hint failed"
set `wc -c 1992/ant.hint`;Wc_c=$1
if test "$Wc_c" != "656"; then
	echo original size 656, current size $Wc_c
fi
# ============= 1992/ant.test.mk ==============
echo "x - extracting 1992/ant.test.mk (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/ant.test.mk &&
X#
X#	Test makefile for AM
X#
X
X#
X#  Allow for empty macros.
X#
XEMPTY=
X
X#
X#  Allow for white space in macro assignment.
X#
XTEXT_1=no white space
XTEXT_2 =left hand side
XTEXT_3= right hand side
XTEXT_4 = both sides
XTEXT_5	=	tabs boths sides
X
X#
X#  Test psuedo targets.
X#
Xall : print_macros repeat redefine many flags multiple split errors done
X
Xprint_macros : empty t1 t2 t3 t4 t5 t.all
X
X#
X#  Targets with no dependencies.
X#
Xempty :
X	echo EMPTY='$(EMPTY)'
X
Xt1 :
X	echo TEXT_1='$(TEXT_1)'
X
Xt2 :
X	echo TEXT_2='$(TEXT_2)'
X
Xt3 :
X	echo TEXT_3='$(TEXT_3)'
X
Xt4 :
X	echo TEXT_4='$(TEXT_4)'
X
Xt5 :
X	echo TEXT_5='$(TEXT_5)'
X
Xt.all :
X	echo $(TEXT_1) $(TEXT_2) $(TEXT_3) $(TEXT_4) $(TEXT_5)
X
X#
X#  Test redefinition of macros.  AM allows redefinition and 
X#  evaluates macros immediately.
X#
XTEXT_1	=text number 1
XTEXT_2	= test macro split \
X	across lines \
X	three lines
XTEXT_3	= test dollar macro '$$'
XTEXT_4	= test dollar again "$$(TEXT_1)"
XTEXT_5	=	imbeded macro '$(TEXT_1)'
X
Xredefine : r1 r2 r3 r4 r5 
X
Xr1 :
X	echo TEXT_1='$(TEXT_1)'
X
Xr2 :
X	echo TEXT_2='$(TEXT_2)'
X
Xr3 :
X	echo TEXT_3='$(TEXT_3)'
X
Xr4 :
X	echo TEXT_4='$(TEXT_4)'
X
Xr5 :
X	echo TEXT_5='$(TEXT_5)'
X
X#
X#  Try to update a prerequisite more than once.  Subsequent occurences
X#  should be ignored once a prerequisite has been updated.
X#
Xrepeat: t1 repeat.a t3
Xrepeat.a : t2 t1
X
X
X#
X#  Target with multi-line receipe.
X#
Xmany : leaf.1 leaf.2
X	echo Execute receipe with multiple commands.
X	ls -1 leaf.*
X	echo Last line of receipe for target 'many'.
X
Xleaf.1 :
X	touch leaf.1
X
Xleaf.2 : 
X	touch leaf.2
X
X
X#
X#  Test receipe line flags.
X#
Xflags : silence ignore always combination
X
X#  Command not displayed before execution.
Xsilence :
X	echo You should not see the 'ls' command printed. 
X	@ls leaf.*
X
X#  Ignore errors from command.
Xignore :
X	echo The 'ls' command should fail but not terminate AM.
X	-ls unknown
X
X#  This flag is ignored by AM since we don't support a silence option (-n).
Xalways :
X	+echo The '+' flag is accepted and ignored.
X
Xcombination:
X	-@echo The next displayed line should not be 'ls unknown'
X	@-ls unknown
X	@+-echo Combined flags test completed.
X
X
X#
X#  Multiple targets.
X#
Xmultiple : node.2 node.5
X
Xnode.1 node.2 node.3 : leaf.1 leaf.2
X	touch node.1 node.2 node.3
X
Xnode.4 node.5 : node.2 leaf.3 
X	touch node.4 node.5
X
Xleaf.3 :
X	touch leaf.3
X
X
X#
X#  Test split lines.
X#
Xsplit : node.6 leaf.4 split.cmd
X	echo Completed split line tests.
X
X#  Target dependencies split across lines.
Xnode.6 : leaf.1 \
X	leaf.2 \
X	leaf.3
X	echo Test dependency list split across lines.
X	touch node.6
X
X#  Target list split across lines.
Xsplit.tar \
Xleaf.4 \
Xleaf.5 :
X	echo Test target list split across lines
X	touch leaf.4 leaf.5 
X
X#  Command lines split across lines.
Xsplit.cmd:
X	echo Try spliting command \
X		lines across more \
X	than one line.
X
X
X#
X#  Test AM error reports and exit statuses.
X#
Xerrors:
X	-am test.mk error.1
X	-am test.mk error.2
X	-am test.mk error.3
X	
X#  Target that does not exist, has no dependencies, and no commands.
Xerror.1:
X
X#  Target where dependency does not exist.
Xerror.2: unknown
X
X#  Receipe command causes error.
Xerror.3: t1 fail t2
Xfail:
X	ls -l unknown
X
X
X#
X#
X#
Xdone:
X	echo AM Test Complete
X
Xclean:
X	rm leaf.* node.*
SHAR_EOF
$TOUCH -am 0817110092 1992/ant.test.mk &&
chmod 0444 1992/ant.test.mk ||
echo "restore of 1992/ant.test.mk failed"
set `wc -c 1992/ant.test.mk`;Wc_c=$1
if test "$Wc_c" != "3164"; then
	echo original size 3164, current size $Wc_c
fi
# ============= 1992/buzzard.1.c ==============
echo "x - extracting 1992/buzzard.1.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.1.c &&
X#define A(c,a,b) t=b;t+=a;_(c)
X#define	B(b,a) P(u,a)t=0;t-=a;R t+=u;t+=1;t/=2;_(b)
X#define b(x) x(g)
X#define C ;main(argc,argv)char**argv;{for(;!w;){q=0;l
X#define c(y) x
X#define D(c,a,b) t=a;t/=b;_(c)
X#define d(x) S(x,x,1)
X#define E(a,d) t=d;t-=p;t*=r;t*=a;p+=t;t=1;t-=a;r*=t;
X#define e(x) y
X#define f(x) x(e)
X#define G(x,y) Q(x,atoi(argv[y]))
X#define g(x) x(b)
X#define H Q(w,1)Q(p,0)r=0;
X#define h(x) x(c)
X#define i(c,a,b) a(b,b,c)
X#define J(x) Q(p,x)r=0;
X#define j(x) Q(f(g),x)
X#define K(x) Q(x,argc)
X#define k(x) S(a,y,x)
X#define L(x) u=p;u-=x;t=u;t*=u;R r+=2;r-=t;r/=2;
X#define l L(q) q+=1;
X#define M(c,a,b) t=a;t*=b;_(c)
X#define m(x) x(a,a)
X#define n(x) x(a,y)
X#define O(c,a,b) t=b;t+=1;t+=a;t/=2;Q(c,t)
X#define o(x,y) M(x,x,y)
X#define P(b,a) t=a;R _(b)
X#define R t+=2047;t/=2048;t+=8191;t/=8192;
X#define Q(a,b) t=b;_(a)
X#define S(c,a,b) t=a;t-=b;_(c)
X#define T }
X#define U(c,a,b) u=b;t=b;t-=1;t*=r;t+=1;b=t;t=a;t/=b;b=u;_(c)
X#define V int t,u,q,p=0,r,w=0,
X#define X(y) printf("%x\n",y);
X#define Z(a,d) t=p;t-=d;t*=a;t+=d;_(p)r*=a;
X#define _(a) t-=a;t*=r;a+=t;
X
XV a,x,y,s C
X
X	    G(f(g),q)G(          g(h),2)n(B)Z(a,4)n(
X	P)E(a,1)j(2989)H l k     (1)m(B)Z(a,6)l k(h(b))
X      B(s,a             )m(P)        Z(s             ,8)E
X    (a,q                   )Q(       s,h               (g)
X   )Q(                               f(c                ),f
X  (g)                                )j(                s)l
X  i(b                                (h)                ,S,
X f(b                                 ))n               (B)
X E(a                                 ,2)             J(8)
Xl j(                                x)Q(x,1)l n(P)Z(a,8
X)o(x                                ,g(f))d(f(e))J(5)l j
X(x)l                                 d(x              )S(a
X ,x,                                 1)m                (B)
X  Z(a                                ,10                 )U(
X  a,y                                ,x)                 o(a
X   ,x)                               k(a                 )m(
X    P)E(                   a,7)      l j                (0)
X      Q(s,1            )l D(a        ,x,              q)o(
X	a,q)S(a,h(g),a)i(s,       M,a)i(a,A,g(f))i(q,D,x
X	    )o(s,16)B(a          ,x)E(a,9)H l j(2766)H
X
XT  X(b(f))  T
SHAR_EOF
$TOUCH -am 0817110092 1992/buzzard.1.c &&
chmod 0444 1992/buzzard.1.c ||
echo "restore of 1992/buzzard.1.c failed"
set `wc -c 1992/buzzard.1.c`;Wc_c=$1
if test "$Wc_c" != "2236"; then
	echo original size 2236, current size $Wc_c
fi
# ============= 1992/buzzard.1.hint ==============
echo "x - extracting 1992/buzzard.1.hint (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.1.hint &&
XMost Obfuscated Algorithm: <sean@stat.tamu.edu> Sean Barrett
X
X	Sean Barrett
X	Software Construction Company
X	430 Southwest Parkway, #1906
X	College Station, TX 77840
X	USA
X
X	Direct bounced email to <jon@stat.tamu.edu>.
X
XJudges' comments:
X
X    To see clearly why this won an award:
X	make babble
X    
X    Try:
X	babble 0 10
X	babble 56 720
X	babble 1 521
X    
X    To see good C Preprocessor babble, try:
X	make babble.cppcb
X	cat babble.cppcb
X    
X    Notice how many statements it takes to do anything useful?
X
X
XSelected notes from the author:
X
X    What you shouldn't think about babble:
X
X      babble doesn't just do a mass of #defines as its obfuscation.
X
X
X    What you should be glad about:
X
X      I didn't just submit the post-C-preprocessed output as an entry.
X
X
X    Cute trick warning:
X
X      babble contains only a numeric printf, yet sometimes it prints out
X      short strings.
X
X
X    What it does:
X
X      babble is a simple mathematical program. It expects two numeric
X      arguments.
X
X      % babble 0 <num>
X      will print out the factorial of <num>.
X
X      % babble <num1> <num2>
X      will print out the largest common factor of num1 and num2.
X
X      % babble 1 <num2>
X      will print out a factor of num2 if it's composite, or else
X      it will print a string informing you that num2 is prime.
X
X      If the first argument is less than 0, it prints out an
X      error message.
X
X
X    What it is:
X
X      babble is a translator from a pseudo-assembly language into a
X      subset of C suitable for execution on Charles Babbage's
X      Analytical Engine.  Or rather, the #defines in babble are that
X      translator.  The rest of babble is a babble program.  If you run the
X      whole mess through CPP and a beautifier, you will see that
X      all you have is a loop that runs until a variable is not 0, and
X      a sequence of assignment statements.  The assignment statements
X      are all of the form 'a op= b' or 'a = b'.  The Engine actually
X      allowed 'a = b op c'.  Only +, -, /, and * are used--no boolean
X      or bitwise operators.  The infinite loop could have been
X      simulated on the AE by connecting the already-processed 
X      card stack to the input card stack.
X
X
X    How to try to understand it:
X
X      *Don't* expand the #defines!  Rather, decipher what they do.
X      Some of them are mere obfuscational fodder, put in to encourage
X      you to run it through CPP.
X
X
X    What it doesn't quite do right as an emulator:
X
X      Because of the definitional constraints, calls to atoi(argv[#])
X      also appear inside the loop.  These could be put outside--
X      the initial values of the "registers" on the AE--but the
X      macro conventions being used didn't lend themselves to it.
X
X
X    Theoretical observations:
X
X      The simulated comparison operations only work with a certain
X      range of numbers; numbers that are too large will cause the
X      output code to fail to simulate the input code.  This means
X      that this implementation of babble would not be turing-complete,
X      even if the AE could process indefinitely-sized numbers.
X      However, this is actually a constraint that no actual computer
X      can meet, either, so we can conclude that if an AE, with
X      card bins connected as suggested above, were hooked up to
X      a memory unit of sufficient size, it would be as turing
X      complete as any existing machine (or, for those who
X      interpret that excessively critically, i.e. "not at all" for
X      both, we can simply say that the AE could simulate any
X      existing machine--although not quickly).  This would be a
X      good place to site some references on the AE, but I don't
X      have any.
X
X
X    Definition of the input language to babble:
X    (OR What Exactly Do All The Macros Do?)
X
X    [Don't read this unless you're stumped!]
X
X
X      MACRO		FUNCTION				MNEMONIC
X        V               begin variable declarations		Variable
X        C               begin program				Code
X
X        Q(b,a)          let b = a				eQuals
X        A(c,a,b)        let c = a + b				Add
X        S(c,a,b)        let c = a - b				Subtract
X        D(c,a,b)        let c = a / b, where b is a *constant*  Divide
X        U(c,a,b)        let c = a / b, where b is anything      Unknown
X        M(c,a,b)        let c = a * b				Multiply
X
X        O(c,a,b)        let c = a boolean-or b (a,b are 0 or 1) Or
X        B(b, a)         let b = boolean value of a		Boolean
X        P(b, a)         let b = 1 if a>0, else 0.		Positive
X
X        l               emit next sequential label		Label
X        J(x)            goto label #x				Jump
X
X        Z(a,d)          if a is 0 goto d    (a is 0 or 1)	Zero
X        E(a,d)          if a is 1 goto d    (a is 0 or 1)	Else
X
X        H               halt					Haly
X
X        K(x)            let x = number of cmd line arguments	Kount
X        G(x,y)          let x = the value if the yth argument   Get argument
X
X        T               end of code; begin output section	Terminate
X        X(y)            print out hexadecimal value of y	heXadecimal
X        T               end of output section and program	Terminate
X
X        You can figure out the other macros yourself.  In the sample
X        program, I've actually implemented subroutines by saving
X        a return address in a variable and then jumping to a routine--
X        specifically, a routine that converts a number into bcd, so
X        it can be output by the hexadecimal output statement.
X
X
X    How it works, i.e., how to get useful programs from a op= b
X
X      The essential statement to be able to do to do interesting
X      programs is the conditional (given that we have loops).
X      Since all you can do in the given operation output set is
X      assignment, we implement "conditional assignment":
X
X        if (x) y = z;
X
X      To implement this, we constrain x to be either 0 or 1, and
X      simply compute:
X
X        y = (z * x) + (y * (1-x));
X
X      This is more obscured by factoring out common terms and restricting
X      ourselves to two operand operations:
X
X        temp = z;                       (temp == z)
X        temp -= y;                      (temp == z-y)
X        temp *= x;                      (temp == (z-y)*x)
X        y += temp;                      (y    == (z-y)*x + y)
X                                        (     == z*x - y*x + y)
X                                        (     == z*x + y*(1-x))
X
X      Next we imagine we have a pc.  "I'm supposed to execute statement
X      pc next", says our emulator.  But suppose we're not currently
X      coming up on statement pc.  To handle this, we simply make every
X      operation conditional on the pc having the correct value:
X
X        if (pc == some_constant) y = z;
X
X      To combine this with other operations, we simply multiply by our
X      (pc == some_constant) flag right after the above 'temp *= x'.
X
X      To evaluate pc == some_constant requires one more trick.  We assume
X      that numbers can only be in some limited range.  Then we use successive
X      additions and divisions to reduce that number down to -1, 0, or 1.
X      You could, for instance, do this by using mod by 2 and div by 2 to
X      count bits, stopping after, say, 32 iterations.  The number you get
X      is between 0..32, so another 6 iterations on it reduces it to 0..6.
X      Three iterations on this produces 0..2 (3 would be '7'), and then
X      two iterations on this produces 0 or 1.  Instead I use a shorter
X      two-divide approach that assumes I'm allowed to use numbers slightly 
X      larger than the numbers I'm operating on.
X
X      A similar approach is used to detect positive numbers.
X
X      Note that the obvious code to compute y/x will not work correctly,
X      because every value is computed, even if the pc is not set correctly;
X      if x is ever 0 when the real C code reaches this computation the
X      program will die.  (This was discovered the hard way.)  The solution
X      is to stick x in a temporary, and if the current code is not about
X      to be executed, set the temporary to 1.
X  
X    Thanks to Bill Pugh for bringing the loopability of the AE to
X    my attention.
X
X    babble was originally named 'cb', for obvious reasons, and is
X    dedicated to the memory of Charles Barrett.
SHAR_EOF
$TOUCH -am 0908160292 1992/buzzard.1.hint &&
chmod 0444 1992/buzzard.1.hint ||
echo "restore of 1992/buzzard.1.hint failed"
set `wc -c 1992/buzzard.1.hint`;Wc_c=$1
if test "$Wc_c" != "8217"; then
	echo original size 8217, current size $Wc_c
fi
# ============= 1992/buzzard.2.README ==============
echo "x - extracting 1992/buzzard.2.README (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.2.README &&
Xbuzzard.2.README	this file
Xbuzzard.2.design	description of FIRST (design documentation of THIRD)
Xthird			implementation of THIRD in FIRST
Xhelp.th			online listing of THIRD primitives
X
X	FIRST demos:  use  'first < {demo}'
X
Xdemo1.1st		prints Hello World! assuming ASCII
X
X	THIRD demos:  use  'cat third {demo} | first'
X
Xdemo1.th		prints Hello World! regardless of character set
Xdemo2.th		demonstrates a simple loop
Xdemo3.th		demonstrates a simple if test
Xdemo4.th		recursive factorial calculating on the way up
Xdemo5.th		recursive factorial calculating on the way down
Xdemo6.th		demonstrates switching from compiler to execution mode
X
X	Interactive THIRD: use 'cat third - | first'.
X
X	To include the primitive on-line help, use
X	'cat third help.th - | first'.
SHAR_EOF
$TOUCH -am 0817110092 1992/buzzard.2.README &&
chmod 0444 1992/buzzard.2.README ||
echo "restore of 1992/buzzard.2.README failed"
set `wc -c 1992/buzzard.2.README`;Wc_c=$1
if test "$Wc_c" != "756"; then
	echo original size 756, current size $Wc_c
fi
# ============= 1992/buzzard.2.c ==============
echo "x - extracting 1992/buzzard.2.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.2.c &&
X#define c m[m[0]++] =
X#define z;break;case
X
Xchar s[5000];
Xint m[20000]={32},L=1,I,T[500],*S=T,t=64,w,f;
X
Xa(x)
X{
X   c L;
X   L= *m-1;
X   c t;
X   c x;
X   scanf("%s",s+t);
X   t+=strlen(s+t)+1;
X}
X
Xr(x)
X{
X   switch(m[x++]){
X	z 5:	for(w=scanf("%s",s)<1?exit(0),0:L;strcmp(s,&s[m[w+1]]);w=m[w]);
X		w-1 ? r(w+2) : (c 2,c atoi(s))
X	z 12:	I=m[m[1]--]
X	z 15:	f=S[-f]
X	z 1:	c x 
X	z 9:	f *=* S--
X	z 7:	m[f]= *S--;
X		f= *S--
X	z 0:	*++S=f;
X		f=m[I++]
X	z 8:	f= *S --- f
X	z 2:	m[++m[1]]=I;
X		I=x
X	z 11:	f=0>f
X	z 4:	*m-=2;c 2
X	z 6:	f=m[f]
X	z 10:	f= *S--/f
X	z 3:	a(1);
X		c 2
X	z 13:	putchar(f);
X		f= *S--
X	z 14:	*++S=f;
X		f=getchar();
X   }
X}
X
Xmain()
X{
X   a(3);
X   a(4);
X   a(1);
X   w= *m;
X   c 5;
X   c 2;
X   I= *m;
X   c w;
X   c I-1;
X   for(w=6;w<16;)
X      a(1),c w++;
X   m[1]= *m;
X   for(*m+=512;;r(m[I++]));
X}
SHAR_EOF
$TOUCH -am 0817110492 1992/buzzard.2.c &&
chmod 0444 1992/buzzard.2.c ||
echo "restore of 1992/buzzard.2.c failed"
set `wc -c 1992/buzzard.2.c`;Wc_c=$1
if test "$Wc_c" != "791"; then
	echo original size 791, current size $Wc_c
fi
echo "End of part 2, continue with part 3"
exit 0
-- 
For a good prime, call:  391581 * 2^216193 - 1
Newsgroups: comp.lang.c