home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume32
/
ioccc.1992
/
part01
next >
Wrap
Text File
|
1992-09-11
|
56KB
|
1,497 lines
Newsgroups: comp.sources.misc
From: chongo@toad.com (Landon Curt Noll)
Subject: v32i028: ioccc.1992 - 1992 International Obfuscated C Code Contest winners, Part01/05
Message-ID: <csm-v32i028=ioccc.1992.103926@sparky.IMD.Sterling.COM>
X-Md4-Signature: fced55eeed9eefb316aacae723a465d0
Date: Thu, 10 Sep 1992 15:40:38 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: chongo@toad.com (Landon Curt Noll)
Posting-number: Volume 32, Issue 28
Archive-name: ioccc.1992/part01
Environment: C
Enclosed is the first of a 5 part shar file containing the winners of
the 1992 International Obfuscated C Code Contest.
First, we congratulate the winners for doing a fine job. Their efforts
and feedback have resulted another good year for the contest.
Second, the 1993 contest will not open until early March 1993. The
rules are expected to be very similar to the 1992 rules, though the
input format will change slightly. Please wait for the 1993 rules
to be posted before submitting 1993 entries.
Third, an International Obfuscated Perl contest is being considered.
Larry Wall and Landon Curt Noll plan to formulate the contest rules
(and a contest name) sometime this year. Watch comp.lang.perl for
details. Send contest ideas (but not entries!) to chongo@toad.com.
Last, we would like to make an apology to the 1992 winners and to the
net for the delay in posting of these results. The poster of this
article (chongo) went on vacation, held extended discussions with
several of the contest winners and attempted to deal with one entry
that appears to conflict with US export regulations.
If you find problems with some of the contest entries, or find typos
in our notes, please send ->PATCH FILES OR COMPLETE FILES<- containing
the corrections to:
judges@toad.com -or- ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
chongo <Landon Curt Noll> /\cc/\ hoptoad!chongo
Larry Bassel {uunet,ucbvax,cbosgd}|sun!lab
p.s. previous winners are available on ftp.uu.net via anonymous ftp
under the directory ~/pub/ioccc. Any 'patches' to the 1992 winners
will be deposited there in a few months.
=-=
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.
---- Cut Here and unpack ----
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: 1992 1992/buzzard.2.design 1992/gson.c 1992/guidelines
# Wrapped by kent@sparky on Thu Sep 10 10:21:20 1992
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 1 (of 5)."'
if test ! -d '1992' ; then
echo shar: Creating directory \"'1992'\"
mkdir '1992'
fi
if test -f '1992/buzzard.2.design' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'1992/buzzard.2.design'\"
else
echo shar: Extracting \"'1992/buzzard.2.design'\" \(25773 characters\)
sed "s/^X//" >'1992/buzzard.2.design' <<'END_OF_FILE'
X FIRST & THIRD
X almost FORTH
X
X FORTH is a language mostly familiar to users of "small" machines.
XFORTH programs are small because they are interpreted--a function
Xcall in FORTH takes two bytes. FORTH is an extendable language--
Xbuilt-in primitives are indistinguishable from user-defined
X_words_. FORTH interpreters are small because much of the system
Xcan be coded in FORTH--only a small number of primitives need to
Xbe implemented. Some FORTH interpreters can also compile defined
Xwords into machine code, resulting in a fast system.
X
X FIRST is an incredibly small language which is sufficient for
Xdefining the language THIRD, which is mostly like FORTH. There are
Xsome differences, and THIRD is probably just enough like FORTH for
Xthose differences to be disturbing to regular FORTH users.
X
X The only existing FIRST interpreter is written in obfuscated C,
Xand rings in at under 800 bytes of source code, although through
Xdeletion of whitespace and unobfuscation it can be brought to about
X650 bytes.
X
X This document FIRST defines the FIRST environment and primitives,
Xwith relevent design decision explanations. It secondly documents
Xthe general strategies we will use to implement THIRD. The THIRD
Xsection demonstrates how the complete THIRD system is built up
Xusing FIRST.
X
X
XSection 1: FIRST
X
X
XEnvironment
X
X FIRST implements a virtual machine. The machine has three chunks
Xof memory: "main memory", "the stack", and "string storage". When
Xthe virtual machine wishes to do random memory accesses, they come
Xout of main memory--it cannot access the stack or string storage.
X
X The stack is simply a standard LIFO data structure that is used
Ximplicitly by most of the FIRST primitives. The stack is made up
Xof ints, whatever size they are on the host machine.
X
X String storage is used to store the names of built-in and defined
Xprimitives. Separate storage is used for these because it allows
Xthe C code to use C string operations, reducing C source code size.
X
X Main memory is a large array of ints. When we speak of
Xaddresses, we actually mean indices into main memory. Main memory
Xis used for two things, primarily: the return stack and the dictionary.
X
X The return stack is a LIFO data structure, independent of
Xthe abovementioned "the stack", which is used by FIRST to keep
Xtrack of function call return addresses.
X
X The dictionary is a list of words. Each word contains a header
Xand a data field. In the header is the address of the previous word,
Xan index into the string storage indicating where the name of this
Xword is stored, and a "code pointer". The code pointer is simply
Xan integer which names which "machine-language-primitive" implements
Xthis instruction. For example, for defined words the code pointer
Xnames the "run some code" primitive, which pushes the current program
Xcounter onto the return stack and sets the counter to the address of
Xthe data field for this word.
X
X There are several important pointers into main memory. There is
Xa pointer to the most recently defined word, which is used to start
Xsearches back through memory when compiling words. There is a pointer
Xto the top of the return stack. There is a pointer to the current
Xend of the dictionary, used while compiling.
X
X For the last two pointers, namely the return stack pointer and
Xthe dictionary pointer, there is an important distinction: the pointers
Xthemselves are stored in main memory (in FIRST's main memory). This
Xis critical, because it means FIRST programs can get at them without
Xany further primitives needing to be defined.
X
X
XInstructions
X
X There are two kinds of FIRST instructions, normal instructions and
Ximmediate instructions. Immediate instructions do something significant
Xwhen they are used. Normal instructions compile a pointer to their
Xexecutable part onto the end of the dictionary. As we will see, this
Xmeans that by default FIRST simply compiles things.
X
X Integer Operations
XSymbol Name Function
X - binary minus pop top 2 elements of stack, subtract, push
X * multiply pop top 2 elements of stack, multiply, push
X / divide pop top 2 elements of stack, divide, push
X <0 less than 0 pop top element of stack, push 1 if < 0 else 0
X
XNote that we can synthesize addition and negation from binary minus,
Xbut we cannot synthesize a time efficient divide or multiply from it.
X<0 is synthesizable, but only nonportably.
X
X Memory Operations
XSymbol Name Function
X @ fetch pop top of stack, treat as address to push contents of
X ! store top of stack is address, 2nd is value; store to memory
X and pop both off the stack
X
X Input/Output Operations
XName Function
Xecho output top of stack through C's putchar()
Xkey push C's getchar() onto top of stack
X_read read a space-delimited word, find it in the
X dictionary, and compile a pointer to
X that word's code pointer onto the
X current end of the dictionary
X
XAlthough _read could be synthesized from key, we need _read to be able
Xto compile words to be able to start any syntheses.
X
X Execution Operations
XName Function
Xexit leave the current function: pop the return stack
X into the program counter
X
X Immediate (compilation) Operations
XSymbol Name Function
X : define read in the next space-delimited word, add it to
X the end of our string storage, and generate
X a header for the new word so that when it
X is typed it compiles a pointer to itself
X so that it can be executed.
Ximmediate immediate when used immediately after a name following a ':',
X makes the word being defined run whenever
X it is typed.
X
X: cannot be synthesized, because we could not synthesize anything.
Ximmediate has to be an immediate operation, so it could not be
Xsynthesized unless by default operations were immediate; but that
Xwould preclude our being able to do any useful compilation.
X
X Stack Operations
XName Function
Xpick pop top of stack, use as index into stack and copy up
X that element
X
XIf the data stack were stored in main memory, we could synthesize pick;
Xbut putting the stack and stack pointer in main memory would significantly
Xincrease the C source code size.
X
X There are three more primitives, but they are "internal only"--
Xthey have no names and no dictionary entries. The first is
X"pushint". It takes the next integer out of the instruction stream
Xand pushes it on the stack. This could be synthesized, but probably
Xnot without using integer constants. It is generated by _read when
Xthe input is not a known word. The second is "compile me". When
Xthis instruction is executed, a pointer to the word's data field is
Xappended to the dictionary. The third is "run me"--the word's data
Xfield is taken to be a stream of pointers to words, and is executed.
X
X One last note about the environment: FIRST builds a very small
Xword internally that it executes as its main loop. This word calls
X_read and then calls itself. Each time it calls itself, it uses
Xup a word on the return stack, so it will eventually trash things.
XThis is discussed some more in section 2.
X
X
XHere's a handy summary of all the FIRST words:
X
X - * / binary integer operations on the stack
X <0 is top of stack less than 0?
X @ ! read from or write to memory
X echo key output or input one character
X _read read a word from input and compile a pointer to it
X exit stop running the current function
X : compile the header of a definition
X immediate modify the header to create an immediate word
X
X Here is a sample FIRST program. I'm assuming you're using
Xthe ASCII character set. FIRST does not depend upon ASCII, but
Xsince FIRST has no syntax for character constants, one normally has
Xto use decimal values. This can be gotten around using getchar, though.
XOh. One other odd thing. FIRST initially builds its symbol table
Xby calling : several times, so it needs to get the names of the base
Xsymbols as its first 13 words of input. You could even name them
Xdifferently if you wanted.
X These FIRST programs have FORTH comments in them: they are contained
Xinside parentheses. FIRST programs cannot have FORTH comments; but I need
Xsome device to indicate what's going on. (THIRD programs are an entirely
Xdifferent subject.)
X
X ( Our first line gives the symbols for the built-ins )
X: immediate _read @ ! - * / <0 exit echo key _pick
X
X ( now we define a simple word that will print out a couple characters )
X
X: L ( define a word named 'L' )
X 108 echo ( output an ascii 'l' )
X exit
X
X: hello ( define a word named 'hello')
X 72 echo ( output an ascii 'H' )
X 101 echo ( output an ascii 'e' )
X 111 ( push ascii 'o' onto the stack )
X L L ( output two ascii 'l's )
X echo ( output the 'o' we pushed on the stack before )
X 10 echo ( print a newline )
X exit ( stop running this routine )
X
X: test immediate ( define a word named 'test' that runs whenever typed )
X hello ( call hello )
X exit
X
Xtest
X
X( The result of running this program should be:
XHello
X)
X
X
XSection 2: Motivating THIRD
X
X What is missing from FIRST? There are a large number of
Ximportant primitives that aren't implemented, but which are
Xeasy to implement. drop , which throws away the top of the
Xstack, can be implemented as { 0 * + } -- that is, multiply
Xthe top of the stack by 0 (which turns the top of the stack
Xinto a 0), and then add the top two elements of the stack.
X
X dup , which copies the top of the stack, can be easily
Ximplemented using temporary storage locations. Conveniently,
XFIRST leaves memory locations 3, 4, and 5 unused. So we can
Ximplement dup by writing the top of stack into 3, and then
Xreading it out twice: { 3 ! 3 @ 3 @ }.
X
X we will never use the FIRST primitive 'pick' in building THIRD,
Xjust to show that it can be done; 'pick' is only provided because
Xpick itself cannot be built out of the rest of FIRST's building
Xblocks.
X
X So, instead of worrying about stack primitives and the
Xlike, what else is missing from FIRST? We get recursion, but
Xno control flow--no conditional operations. We cannot at the
Xmoment write a looping routine which terminates.
X
X Another glaring dissimilarity between FIRST and FORTH is
Xthat there is no "command mode"--you cannot be outside of a
X: definition and issue some straight commands to be executed.
XAlso, as we noted above, we cannot do comments.
X
X FORTH also provides a system for defining new data types,
Xusing the words [in one version of FORTH] <builds and does> .
XWe would like to implement these words as well.
X
X As the highest priority thing, we will build control flow
Xstructures first. Once we have control structures, we can
Xwrite recursive routines that terminate, and we are ready to
Xtackle tasks like parsing, and the building of a command mode.
X
X By the way, location 0 holds the dictionary pointer, location
X1 holds the return stack pointer, and location 2 should always
Xbe 0--it's a fake dictionary entry that means "pushint".
X
X
XSection 3: Building THIRD
X
X In this section, I'm going to keep my conversation
X indented to this depth, rather than using fake comments--
X because we'll have real comments eventually.
X
X The first thing we have to do is give the symbols for our
X built-ins.
X
X: immediate _read @ ! - * / < exit echo key _pick
X
X Next we want to be mildly self commenting, so we define
X the word 'r' to push the *address of the return stack
X pointer* onto the stack--NOT the value of the return
X stack pointer. (In fact, when we run r, the value of
X the return stack pointer is temporarily changed.)
X
X: r 1 exit
X
X Next, we're currently executing a short loop that contains
X _read and recursion, which is slowly blowing up the return
X stack. So let's define a new word, from which you can
X never return. What it does is drops the top value off
X the return stack, calls _read, then calls itself. Because
X it kills the top of the return stack, it can recurse
X indefinitely.
X
X: ]
X r @ Get the value of the return stack pointer
X 1 - Subtract one
X r ! Store it back into the return stack pointer
X _read Read and compile one word
X ] Start over
X
X Notice that we don't need to exit, since we never come
X back. Also, it's possible that an immediate word may
X get run during _read, and that _read will never return!
X
X Now let's get compile running.
X
X: main immediate ]
Xmain
X
X Next off, I'm going to do this the easy but non-portable
X way, and put some character constant definitions in.
X I wanted them at the top of the file, but that would have
X burned too much of the return stack.
X
X: '"' 34 exit
X: ')' 41 exit
X: '\n' 10 exit
X: 'space' 32 exit
X: '0' 48 exit
X: '-' 45 exit
X
X: cr '\n' echo exit
X
X Next, we want to define some temporary variables for
X locations 3, 4, and 5, since this'll make our code look
X clearer.
X: _x 3 @ exit
X: _x! 3 ! exit
X: _y 4 @ exit
X: _y! 4 ! exit
X
X Ok. Now, we want to make THIRD look vaguely like FORTH,
X so we're going to define ';'. What ; ought to do is
X terminate a compilation, and turn control over to the
X command-mode handler. We don't have one, so all we want
X ';' to do for now is compile 'exit' at the end of the
X current word. To do this we'll need several other words.
X
X Swap by writing out the top two elements into temps, and
X then reading them back in the other order.
X: swap _x! _y! _x _y exit
X Take another look and make sure you see why that works,
X since it LOOKS like I'm reading them back in the same
X order--in fact, it not only looks like it, but I AM!
X
X Addition might be nice to have. To add, we need to
X negate the top element of the stack, and then subtract.
X To negate, we subtract from 0.
X: +
X 0 swap -
X -
X exit
X
X Create a copy of the top of stack
X: dup _x! _x _x exit
X
X Get a mnemonic name for our dictionary pointer--we need
X to compile stuff, so it goes through this.
X: h 0 exit
X
X We're going to need to advance that pointer, so let's
X make a generic pointer-advancing function.
X Given a pointer to a memory location, increment the value
X at that memory location.
X: inc
X dup @ Get another copy of the address, and get the value
X so now we have value, address on top of stack.
X 1 + Add one to the value
X swap Swap to put the address on top of the stack
X ! exit Write it to memory
X
X , is a standard FORTH word. It should write the top of
X stack into the dictionary, and advance the pointer
X: ,
X h @ Get the value of the dictionary pointer
X ! Write the top of stack there
X h inc And increment the dictionary pointer
X exit
X
X ' is a standard FORTH word. It should push the address
X of the word that follows it onto the stack. We could
X do this by making ' immediate, but then it'd need to
X parse the next word. Instead, we compile the next word
X as normal. When ' is executed, the top of the return
X stack will point into the instruction stream immediately
X after the ' . We push the word there, and advance the
X return stack pointer so that we don't execute it.
X: '
X r @ Get the address of the top of return stack
X We currently have a pointer to the top of return stack
X @ Get the value from there
X We currently have a pointer to the instruction stream
X dup Get another copy of it--the bottom copy will stick
X around until the end of this word
X 1 + Increment the pointer, pointing to the NEXT instruction
X r @ ! Write it back onto the top of the return stack
X We currently have our first copy of the old pointer
X to the instruction stream
X @ Get the value there--the address of the "next word"
X exit
X
X Now we're set. ; should be an immediate word that pushes
X the address of exit onto the stack, then writes it out.
X: ; immediate
X ' exit Get the address of exit
X , Compile it
X exit And we should return
X
X Now let's test out ; by defining a useful word:
X: drop 0 * + ;
X
X Since we have 'inc', we ought to make 'dec':
X: dec dup @ 1 - swap ! ;
X
X Our next goal, now that we have ;, is to implement
X if-then. To do this, we'll need to play fast and
X loose with the return stack, so let's make some
X words to save us some effort.
X
X First we want a word that pops off the top of the normal
X stack and pushes it on top of the return stack. We'll
X call this 'tor', for TO-Return-stack. It sounds easy,
X but when tor is running, there's an extra value on the
X return stack--tor's return address! So we have to pop
X that off first... We better just bite the bullet and
X code it out--but we can't really break it into smaller
X words, because that'll trash the return stack.
X: tor
X r @ @ Get the value off the top of the return stack
X swap Bring the value to be pushed to the top of stack
X r @ ! Write it over the current top of return stack
X r @ 1 + r ! Increment the return stack pointer--but can't use inc
X r @ ! Store our return address back on the return stack
X;
X
X Next we want the opposite routine, which pops the top
X of the return stack, and puts it on the normal stack.
X: fromr
X r @ @ Save old value
X r @ 1 - r ! Decrement pointer
X r @ @ Get value that we want off
X swap Bring return address to top
X r @ ! Store it and return
X;
X
X Now, if we have a routine that's recursing, and we
X want to be polite about the return stack, right before
X we recurse we can run { fromr drop } so the stack won't
X blow up. This means, though, that the first time we
X enter this recursive routine, we blow our *real* return
X address--so when we're done, we'll return up two levels.
X To save a little, we make 'tail' mean { fromr drop };
X however, it's more complex since there's a new value on
X top of the return stack.
X: tail fromr fromr drop tor ;
X
X Now, we want to do 'if'. To do this, we need to convert
X values to boolean values. The next few words set this
X up.
X
X minus gives us unary negation.
X: minus 0 swap - ;
X
X If top of stack is boolean, bnot gives us inverse
X: bnot 1 swap - ;
X
X To compare two numbers, subtract and compare to 0.
X: < - <0 ;
X
X logical turns the top of stack into either 0 or 1.
X: logical
X dup Get two copies of it
X 0 < 1 if < 0, 0 otherwise
X swap minus Swap number back up, and take negative
X 0 < 1 if original was > 0, 0 otherwise
X + Add them up--has to be 0 or 1!
X;
X
X not returns 1 if top of stack is 0, and 0 otherwise
X: not logical bnot ;
X
X We can test equality by subtracting and comparing to 0.
X: = - not ;
X
X Just to show how you compute a branch: Suppose you've
X compiled a call to branch, and immediately after it is
X an integer constant with the offset of how far to branch.
X To branch, we use the return stack to read the offset, and
X add that on to the top of the return stack, and return.
X: branch
X r @ Address of top of return stack
X @ Our return address
X @ Value from there: the branch offset
X r @ @ Our return address again
X + The address we want to execute at
X r @ ! Store it back onto the return stack
X;
X
X For conditional branches, we want to branch by a certain
X amount if true, otherwise we want to skip over the branch
X offset constant--that is, branch by one. Assuming that
X the top of the stack is the branch offset, and the second
X on the stack is 1 if we should branch, and 0 if not, the
X following computes the correct branch offset.
X: computebranch 1 - * 1 + ;
X
X Branch if the value on top of the stack is 0.
X: notbranch
X not
X r @ @ @ Get the branch offset
X computebranch Adjust as necessary
X r @ @ + Calculate the new address
X r @ ! Store it
X;
X
X here is a standard FORTH word which returns a pointer to
X the current dictionary address--that is, the value of
X the dictionary pointer.
X: here h @ ;
X
X We're ALL SET to compile if...else...then constructs!
X Here's what we do. When we get 'if', we compile a call
X to notbranch, and then compile a dummy offset, because
X we don't know where the 'then' will be. On the *stack*
X we leave the address where we compiled the dummy offset.
X 'then' will calculate the offset and fill it in for us.
X: if immediate
X ' notbranch , Compile notbranch
X here Save the current dictionary address
X 0 , Compile a dummy value
X;
X
X then expects the address to fixup to be on the stack.
X: then immediate
X dup Make another copy of the address
X here Find the current location, where to branch to
X swap - Calculate the difference between them
X swap ! Bring the address to the top, and store it.
X;
X
X Now that we can do if...then statements, we can do
X some parsing! Let's introduce real FORTH comments.
X find-) will scan the input until it finds a ), and
X exit.
X: find-)
X key Read in a character
X ')' = Compare it to close parentheses
X not if If it's not equal
X tail find-) repeat (popping R stack)
X then Otherwise branch here and exit
X;
X
X: ( immediate
X find-)
X;
X
X( we should be able to do FORTH-style comments now )
X
X( now that we've got comments, we can comment the rest of the code
X in a legitimate [self parsing] fashion. Note that you can't
X nest parentheses... )
X
X: else immediate
X ' branch , ( compile a definite branch )
X here ( push the backpatching address )
X 0 , ( compile a dummy offset for branch )
X swap ( bring old backpatch address to top )
X dup here swap - ( calculate the offset from old address )
X swap ! ( put the address on top and store it )
X;
X
X: over _x! _y! _y _x _y ;
X
X: add
X _x! ( save the pointer in a temp variable )
X _x @ ( get the value pointed to )
X + ( add the incremement from on top of the stack )
X _x ! ( and save it )
X;
X
X: allot h add ;
X
X: maybebranch
X logical ( force the TOS to be 0 or 1 )
X r @ @ @ ( load the branch offset )
X computebranch ( calculate the condition offset [either TOS or 1])
X r @ @ + ( add it to the return address )
X r @ ! ( store it to our return address and return )
X;
X
X: mod _x! _y! ( get x then y off of stack )
X _y _y _x / _x * ( y - y / x * x )
X -
X;
X
X: printnum
X dup
X 10 mod '0' +
X swap 10 / dup
X if
X printnum
X echo
X else
X drop
X echo
X then
X;
X
X: .
X dup 0 <
X if
X '-' echo minus
X then
X printnum
X 'space' echo
X;
X
X: debugprint dup . cr ;
X
X( the following routine takes a pointer to a string, and prints it,
X except for the trailing quote. returns a pointer to the next word
X after the trailing quote )
X
X: _print
X dup 1 +
X swap @
X dup '"' =
X if
X drop exit
X then
X echo
X tail _print
X;
X
X: print _print ;
X
X ( print the next thing from the instruction stream )
X: immprint
X r @ @
X print
X r @ !
X;
X
X: find-"
X key dup ,
X '"' =
X if
X exit
X then
X tail find-"
X;
X
X: " immediate
X key drop
X ' immprint ,
X find-"
X;
X
X: do immediate
X ' swap , ( compile 'swap' to swap the limit and start )
X ' tor , ( compile to push the limit onto the return stack )
X ' tor , ( compile to push the start on the return stack )
X here ( save this address so we can branch back to it )
X;
X
X: i r @ 1 - @ ;
X: j r @ 3 - @ ;
X
X: > swap < ;
X: <= 1 + < ;
X: >= swap <= ;
X
X: inci
X r @ 1 - ( get the pointer to i )
X inc ( add one to it )
X r @ 1 - @ ( find the value again )
X r @ 2 - @ ( find the limit value )
X <=
X if
X r @ @ @ r @ @ + r @ ! exit ( branch )
X then
X fromr 1 +
X fromr drop
X fromr drop
X tor
X;
X
X: loop immediate ' inci @ here - , ;
X
X: loopexit
X
X fromr drop ( pop off our return address )
X fromr drop ( pop off i )
X fromr drop ( pop off the limit of i )
X; ( and return to the caller's caller routine )
X
X: execute
X 8 !
X ' exit 9 !
X 8 tor
X;
X
X: :: ; ( :: is going to be a word that does ':' at runtime )
X
X: fix-:: immediate 3 ' :: ! ;
Xfix-::
X
X ( Override old definition of ':' with a new one that invokes ] )
X: : immediate :: ] ;
X
X: command
X here 5 ! ( store dict pointer in temp variable )
X _read ( compile a word )
X ( if we get control back: )
X here 5 @
X = if
X tail command ( we didn't compile anything )
X then
X here 1 - h ! ( decrement the dictionary pointer )
X here 5 @ ( get the original value )
X = if
X here @ ( get the word that was compiled )
X execute ( and run it )
X else
X here @ ( else it was an integer constant, so push it )
X here 1 - h ! ( and decrement the dictionary pointer again )
X then
X tail command
X;
X
X: make-immediate ( make a word just compiled immediate )
X here 1 - ( back up a word in the dictionary )
X dup dup ( save the pointer to here )
X h ! ( store as the current dictionary pointer )
X @ ( get the run-time code pointer )
X swap ( get the dict pointer again )
X 1 - ( point to the compile-time code pointer )
X ! ( write run-time code pointer on compile-time pointer )
X;
X
X: <build immediate
X make-immediate ( make the word compiled so far immediate )
X ' :: , ( compile '::', so we read next word )
X 2 , ( compile 'pushint' )
X here 0 , ( write out a 0 but save address for does> )
X ' , , ( compile a push that address onto dictionary )
X;
X
X: does> immediate
X ' command , ( jump back into command mode at runtime )
X here swap ! ( backpatch the build> to point to here )
X 2 , ( compile run-code primitive so we look like a word )
X ' fromr , ( compile fromr, which leaves var address on stack )
X;
X
X
X: _dump ( dump out the definition of a word, sort of )
X dup " (" . " , "
X dup @ ( save the pointer and get the contents )
X dup ' exit
X = if
X " ;)" cr exit
X then
X . " ), "
X 1 +
X tail _dump
X;
X
X: dump _dump ;
X
X: # . cr ;
X
X: var <build , does> ;
X: constant <build , does> @ ;
X: array <build allot does> + ;
X
X: [ immediate command ;
X: _welcome " Welcome to THIRD.
XOk.
X" ;
X
X: ; immediate ' exit , command exit
X
X[
X
X_welcome
X
END_OF_FILE
if test 25773 -ne `wc -c <'1992/buzzard.2.design'`; then
echo shar: \"'1992/buzzard.2.design'\" unpacked with wrong size!
fi
# end of '1992/buzzard.2.design'
fi
if test -f '1992/gson.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'1992/gson.c'\"
else
echo shar: Extracting \"'1992/gson.c'\" \(1513 characters\)
sed "s/^X//" >'1992/gson.c' <<'END_OF_FILE'
X#include <stdio.h>
X
Xlong a
X[4],b[
X4],c[4]
X,d[0400],e=1;
Xtypedef struct f{long g
X,h,i[4] ,j;struct f*k;}f;f g,*
Xl[4096 ]; char h[256],*m,k=3;
X long n (o, p,q)long*o,*p,*q;{
X long r =4,s,i=0;for(;r--;s=i^
X *o^*p, i=i&*p|(i|*p)&~*o++,*q
X ++=s,p ++);return i;}t(i,p)long*p
X ;{*c=d [i],n(a,c,b),n(p,b,p);}u(j)f*j;{j->h
X =(j->g =j->i[0]|j->i[1]|j->i[2]|j->i[3])&4095;}v(
Xj,s)f* j; {int i; for(j->k->k&&v(j->k, ' '),fseek(
Xstdin, j->j, 0);i=getchar(),putchar(i-'\n'?i:s),i-
X'\n';);}w(o,r,j,x,p)f*o,*j;long p;{f q;int
Xs,i=o->h;q.k=o;r>i?j=l[r=i]:r<i&&
X(s=r&~i)?(s|=s>>1, s|=s
X>>2,s|=s>>4,s
X|=s>>8
X,j=l[r
X=((r&i
X |s)&~(s>>1))-1&i]):0;--x;for
X (;x&&!(p&i);p>>=1);for(;!x&&j;n(o->i,j->i,q.
X i),u(&q),q.g||(q.j=j->j,v(&q,'\n')),j=j->k);for(;x;j=x
X ?j->k:0){for(;!j&&((r=(r&i)-1&i)-i&&(r&p)?2:(x=0));j=l[r]);!
X x||(j->g&~o->g)||n (o->i,j->i,q.i)||(
X u(&q), q.j=j ->j,q.g?w(&q
X ,r,j->k,x ,p):v(&q,
X '\n')); }}y(){f
X j;char *z,*p;
Xfor(;m ? j.j=
Xftell( stdin)
X,7,(m= gets(m ))||w(
X&g,315 *13,l[ 4095]
X ,k,64* 64)&0: 0;n(g
X .i,j.i, b)||(u (&j),j.
X k=l[j.h],l[j.h]= &j,y())){for(z= p=h;*z&&(
X d[*z++]||(p=0)););for(z=p?n(j.i ,j.i,j.i)+h:"";
X *z;t(*z++,j.i));}}main(o,p)char** p; {for(;m = *++p;)for(;*m-
X'-'?*m:(k= -atoi(m))&0;d[*m]||(d[*m ]=e,e<<=1),t(*m++,g.i)); u(&
X g),m=h
X ,y();}
END_OF_FILE
if test 1513 -ne `wc -c <'1992/gson.c'`; then
echo shar: \"'1992/gson.c'\" unpacked with wrong size!
fi
# end of '1992/gson.c'
fi
if test -f '1992/guidelines' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'1992/guidelines'\"
else
echo shar: Extracting \"'1992/guidelines'\" \(22215 characters\)
sed "s/^X//" >'1992/guidelines' <<'END_OF_FILE'
X9th International Obfuscated C Code Contest Guidelines, Hints and Comments
X
X
XABOUT THIS FILE:
X
X This file is intended to help people who wish to submit entries to
X the International Obfuscated C Code Contest (IOCCC for short).
X
X This is not the IOCCC rules, though it does contain comments about
X them. The guidelines should be viewed as hints and suggestions.
X Entries that violate the guidelines but remain within the rules are
X allowed. Even so, you are safer if you remain within the guidelines.
X
X You should read the current IOCCC rules, prior to submitting entries.
X The rules are typically sent out with these guidelines.
X
X
XWHAT IS NEW IN 1992:
X
X The size rules are different this year. There is a more relaxed
X rule to encourage formatting styles beyond rectangular blobs of C
X code. The build file (how to compile) has been expanded as well.
X See the rules, and OUR LIKES AND DISLIKES for details.
X
X The entry format is better (for us anyway). The program mkentry.c
X provides a convenient way to form an entry. See ENTRY FORMAT.
X
X The original entry source, build and resulting binary should be
X treated as read-only. There is a provision to allow entries to
X modify these files indirectly. See ENTRY FORMAT.
X
X This year, we are experimenting with a new category of programs:
X X clients. X client entries should be as portable as possible.
X See OUR LIKES AND DISLIKES.
X
X
XHINTS AND SUGGESTIONS:
X
X You are encouraged to examine the winners of previous contests. See
X FOR MORE INFORMATION for details on how to get previous winners.
X
X Keep in mind that rules change from year to year, so some winning entries
X may not be valid entries this year. What was unique and novel one year
X might be 'old' the next year.
X
X An entry is usually examined in a number of ways. We typically apply
X a number of tests to an entry:
X
X * look at the original source
X * If it is ANSI, convert tri-graphs to ASCII
X * C pre-process the source ignoring '#include' lines
X * C pre-process the source ignoring '#define' and '#include' lines
X * run it through a C beautifier
X * examine the algorithm
X * lint it
X * compile it
X * execute it
X
X You should consider how your entry looks in each of the above tests.
X You should ask yourself if your entry remains obscure after it has been
X 'cleaned up' by the C pre-processor and a C beautifier.
X
X Your entry need not do well under all, or in most tests. In certain
X cases, a test is not important. Entries that compete for the
X 'strangest/most creative source layout' need not do as well as
X others in terms of their algorithm. On the other hand, given
X two such entries, we are more inclined to pick the entry that
X does something interesting when you run it.
X
X We try to avoid limiting creativity in our rules. As such, we leave
X the contest open for creative rule interpretation. As in real life
X programming, interpreting a requirements document or a customer request
X is important. For this reason, we often award 'worst abuse of the
X rules' to an entry that illustrates this point in an ironic way.
X
X If you do plan to abuse the rules, we suggest that you let us know
X in the remarks section. Please note that an invitation to abuse
X is not an invitation to break. We are strict when it comes to the
X 3217 byte size limit. Also, abusing the entry format tends to
X annoy more than amuse.
X
X We do realize that there are holes in the rules, and invite entries
X to attempt to exploit them. We will award 'worst abuse of the rules'
X and then plug the hole next year. Even so, we will attempt to use
X the smallest plug needed, if not smaller. :-)
X
X Check out your program and be sure that it works. We sometimes make
X the effort to debug an entry that has a slight problem, particularly
X in or near the final round. On the other hand, we have seen some
X of the best entries fall down because they didn't work.
X
X We tend to look down on a prime number printer, that claims that
X 16 is a prime number. If you do have a bug, you are better off
X documenting it. Noting "this entry sometimes prints the 4th power
X of a prime by mistake" would save the above entry. And sometimes,
X a strange bug/feature can even help the entry! Of course, a correctly
X working entry is best.
X
X
XOUR LIKES AND DISLIKES:
X
X Doing masses of #defines to obscure the source has become 'old'. We
X tend to 'see thru' masses of #defines due to our pre-processor tests
X that we apply. Simply abusing #defines or -Dfoo=bar won't go as far
X as a program that is more well rounded in confusion.
X
X Many ANSI C compilers dislike the following code, and so do we:
X
X #define d define
X #d foo <-- don't expect this to turn into #define foo
X
X int i;
X j; <-- don't use such implicit type declarations
X int k;
X
X We suggest that you use ANSI C compilers if possible. If you must
X use non-ANSI C, such as K&R C, try to avoid areas that give ANSI C
X compilers problems.
X
X Small programs are best when they are short, obscure and concise.
X While such programs are not as complex as other winners, they do
X serve a useful purpose. They are often the only program that people
X attempt to completely understand. For this reason, we look for
X programs that are compact, and are instructional.
X
X One line programs should be short one line programs, say around 80
X bytes long. Getting close to 160 bytes is a bit too long for one liners
X in our books.
X
X We tend to dislike programs that:
X
X * are very hardware specific
X * are very OS or Un*x version specific
X (index/strchr differences are ok, but socket/streams specific
X code is likely not to be)
X * dump core or have compiler warnings
X (it is ok only if you warn us in the 'remark' header item)
X * won't compile under both BSD or SYS V Un*x
X * abusing the build file to get around the size limit
X * obfuscate by excessive use of ANSI tri-graphs
X * are longer than they need to be
X * are similar to previous winners
X * are identical to previous losers :-)
X
X Unless you are cramped for space, or unless you are entering the
X 'best one liner' category, we suggest that you format your program
X in a more creative way than simply forming excessively long lines.
X
X The build file should not be used to try and get around the size
X limit. It is one thing to make use of a several -D's to help out,
X but it is quite another to use 200+ bytes of -D's in order to
X try and squeeze the source under the size limit. You should feel
X free to make use of the build file space, but you are better off
X if you show some amount of restraint.
X
X We allowed whitespace, and in certain cases ; { or } do not impact
X your program size (up to a certain point), because we want to get
X away from source that is simply a compact blob of characters.
X
X Given two versions of the same program, one that is a compact blob
X of code, and the other that is formatted more like a typical C
X program, we tend to favor the second version. Of course, a third
X version of the same program that is formatted in an interesting
X and/or obfuscated way, would definitely win over the first two!
X
X We suggest that you avoid trying for the 'smallest self-replicating'
X program. We are amazed at the many different sizes that claim
X to be the smallest. There is nothing wrong with self-replicating
X programs. In fact, a number of winners have been self-replicating.
X You might want to avoid the claim of 'smallest', lest we (or others)
X know of a smaller one!
X
X X client entries should be as portable as possible. Entries that
X adapt to a wide collection of environments will be favored. Don't
X depend on a particular type of display. For example, don't depend
X on color or a given size. Don't require backing store.
X
X X client entries should avoid using X related libraries and
X software that is not in wide spread use. We ask that such X client
X entries restrict themselves to only the low level Xlib and the
X Athena widget set (libX11.a, libXaw.a, libXmu.a and libXt.a).
X Don't use M*tif, Xv*ew, or OpenL*ok toolkits, since not everyone
X has them. Avoid depending on a particular window manager. Not
X everyone has X11r5, and some people are stuck back in X11r3 (or
X earlier), so try to target X11r4 without requiring X11r4. Better
X yet, try to make your entry run on all version 11 X Window Systems.
X
X X client entries should not to depend on particular items on
X .Xdefaults. If you must do so, be sure to note the required lines
X in the ---remark--- section. Better yet, give an xrdb -merge
X command as part of the build.
X
X We like programs that:
X
X * are as concise and small as they need to be
X * do something at least quasi-interesting
X * pass lint without complaint (not a requirement, but it is nice)
X * are portable
X * are unique or novel in their obfuscation style
X * MAKE USE OF A NUMBER OF DIFFERENT TYPES OF OBFUSCATION
X * make us laugh and/or throw up :-)
X
X Some types of programs can't excel in some areas. Of course, your
X program doesn't have to excel in all areas, but doing well in several
X areas really does help.
X
X We freely admit that interesting, creative or humorous comments in
X the ---remark--- section helps your chance of winning. If you had to
X read of many twisted entries, you too would enjoy a good laugh or two.
X We think the readers of the contest winners do as well.
X
X Be creative!
X
X
XENTRY FORMAT:
X
X In order to help us process the many entries, we must request your
X assistance by formatting your entries in a certain way. This format,
X in addition, allows us to quickly separate information about the
X author from the program itself. (see JUDGING PROCESS)
X
X We have provided the program, mkentry, as an example of how to
X format entries. You should be aware of the following warning that
X is found in mkentry.c:
X
X This program attempts to implement the IOCCC rules. Every
X attempt has been made to make sure that this program produces
X an entry that conforms to the contest rules. In all cases,
X where this program differs from the contest rules, the
X contest rules will be used. Be sure to check with the
X contest rules before submitting an entry.
X
X You are not required to use mkentry. It is convenient, however,
X as it attempts to uuencode the needed files, and attempt to check
X the entry against the size rules.
X
X If you have any suggestions, comments, fixes or complaints about
X the mkentry.c program, please send Email to the judges. (see below)
X
X The following is a sample entry:
X
X---entry---
Xrule: 1992
Xtitle: chonglab
Xentry: 0
Xdate: Mon Feb 17 13:58:57 1992
Xhost: Un*x v6, pdp11/45
X 2.9BSD, pdp11/70
X---remark---
X This is a non-obfuscated obfuscated C program.
X
X It is likely not to win a prize. But what do you expect from
X a short example! (yes, Hello world progs have become old too)
X---author---
Xname: Landon Curt Noll
Xorg: IOCCC Judging Group
Xaddr: Toad Hall
X San Francisco, CA 94101
X USA
Xemail: chongo@toad.com
Xanon: n
X---author---
Xname: Larry Bassel
Xorg: IOCCC Judging Group
Xaddr: Toad Hall
X San Francisco, CA 94101
X USA
Xemail: hoptoad!sun!lab
X lab@sun.com
Xanon: n
X---info---
Xbegin 444 info.file
XM2&$A("!792!G;W0@>6]U('1O(&QO;VLA"@I4:&%T('1H870@:7,L(&ES+@I4
XM:&%T('1H870@:7,@;F]T+`H@("`@:7,@;F]T('1H870@=&AA="!N;W0@:7,N
XM"E1H870@:7,L('1H870@=&AA="!I<R!N;W0L(&ES(0H*"0DM+2!C:&]N9V\@
X%,3DW-`H@
X`
Xend
X---build---
Xbegin 444 build
X28V,@<')O9RYC("UO('!R;V<*
X`
Xend
X---program---
Xbegin 444 prog.c
XC;6%I;B@I>W!R:6YT9B@B2&5L;&\L('=O<FQD(5QN(BD[?0H`
X`
Xend
X---end---
X
X Where build uudecodes into:
X
Xcc prog.c -o prog
X
X and prog.c uudecodes into:
X
Xmain(){printf("Hello, world!\n");}
X
X Typically the build file should assume that the source is prog.c
X and will compile into prog. If an entry wins, we will rename
X its source and binary to avoid filename collision. By tradition,
X we use the name of the entry's title, followed by an optional
X digit in case of name conflicts.
X
X If the above entry somehow won the 'least likely to win' award,
X we would use chonglab.c and chonglab.
X
X If your entry depends on, or requires that your build, source
X and/or binary files be a particular name, please say so in the
X ---remark--- section. If this case applies, it would be be helpful
X if you did one of the following:
X
X * Tell us how to change the filename(s) in your entry.
X
X * Have the build file make copies of the files. For example:
X
X cc prog.c -o special_name need special binary
X
X or rm -f special_src.c need special source
X cp prog.c special_src.c
X cc special_src.c -o special_name
X
X or rm -f special_build need special build
X tail +4 build > special_build
X sh < special_build
X
X * Assume that we will use the entry title. Send us a version of
X your build/program files that uses the name convention. You
X should uuencode these files in ---data--- sections.
X
X If your entry needs to modify its source, info or binary files,
X please say so in the ---remark--- section. You should try to avoid
X touching your original build, source and binary files. You should
X arrange to make copies of the files you intend to modify. This
X will allow people to re-generate your entry from scratch.
X
X Remember that your entry may be built without a build file. We
X typically incorporate the build lines into a Makefile. If the
X build file must exist, say so in the ---remark--- section.
X
X If your entry needs special info files, you should uuencode them
X into ---info--- sections. In the case of multiple info files,
X use multiple ---info--- sections. If no info files are needed,
X then skip the ---info--- section.
X
X Info files are intended to be input, or detailed information that
X does not fit well into the ---remark--- section. For example, an
X entry that implements a compiler might want to provide some sample
X programs for the user to compile. An entry might want to include a
X lengthly design document, that might not be appropriate for a
X 'hints' file.
X
X Info files should be used only to supplement your entry. For
X example, info files may provide sample input or detailed
X information about your entry. Because they are supplemental,
X the entry should not require them exist.
X
X In some cases, your info files might be renamed to avoid name
X conflicts. If info files should not be renamed for some reason,
X say so in the ---remark--- section.
X
X Info files must uudecode into the current directory. If they
X absolutely must be renamed, or moved into a sub-directory, say
X so in the ---remark--- section.
X
X
XJUDGING PROCESS:
X
X Entries are judged by Larry Bassel and Landon Curt Noll.
X
X Entries are unpacked into individual directories. The Email message
X is unpacked into individual files, each containing:
X
X ---entry--- section
X all ---author--- sections
X all ---info--- sections
X ---build--- section
X ---program--- section
X any other text, including the Email message headers
X
X Prior to judging, the 'any other text' file is scanned to be sure
X it does not contain useful information (or in case the entry was
X malformed and did not unpack correctly). Information from the
X ---author--- sections are not read until the judging process is
X complete, and then only from entries that have won an award.
X
X The above process helps keep us biased for/against any one particular
X individual. We are usually kept in the dark as much as you are
X until the final awards are given. We like the surprise of finding
X out in the end, who won and where they were from.
X
X We attempt to keep all entries anonymous, unless they win an award.
X Because the main 'prize' of winning is being announced, we make all
X attempts to send non-winners into oblivion. We remove all non-winning
X files, and shred all related paper. By tradition, we do not even
X reveal the number of entries that we received. (for the curious,
X we do indicate the volume of paper consumed when presenting the IOCCC
X winners at talks)
X
X After the Usenix announcement, we attempt to send Email to the
X authors of the winning entries. One reason we do this is to give
X the authors a chance to comment on the way we have presented their
X entry. They are given the chance to correct mistakes, typos. We
X often accept their suggestions/comments about our remarks as well.
X This is done prior to posting the winners to the wide world.
X
X Judging consists of a number of elimination rounds. During a round,
X the collection of entries are divided into two roughly equal piles;
X the pile that advances on to the next round, and the pile that does
X not. We also re-examine the entries that were eliminated in the
X previous round. Thus, an entry gets at least two readings.
X
X A reading consists of a number of actions:
X
X * reading the ---entry--- section
X * reading the uudecoded ---build--- section
X * reading the uudecoded ---program--- section
X * reading the uudecoded ---info--- section(s), if any
X * passing the source thru the C pre-processor
X shipping over any #include files
X * performing a number of C beautify/cleanup edits on the source
X * passing the beautified source thru the C pre-processor
X shipping over any #include files
X
X In later rounds, other actions are performed:
X
X * linting the source
X * compiling/building the source
X * running the program
X * performing misc tests on the source and binary
X
X Until we reduce the stack of entries down to about 25 entries, entries
X are judged on an individual basis. An entry is set aside because it
X does not, in our opinion, meet the standard established by the round.
X When the number of entries thins to about 25 entries, we begin to form
X award categories. Entries begin to compete with each other for awards.
X An entry often will compete in several categories.
X
X The actual award category list will vary depending on the types of entries
X we receive. A typical category list might be:
X
X * best small one line program
X * best small program
X * strangest/most creative source layout
X * most useful obfuscated program
X * best game that is obfuscated
X * most creatively obfuscated program
X * most deceptive C code
X * best X client (see OUR LIKES AND DISLIKES)
X * best abuse of ANSI C
X * worst abuse of the rules
X * <anything else so strange that it deserves an award>
X
X We do not limit ourselves to this list. For example, a few entries are so
X good/bad that they are declared winners at the start of the final round.
X We will invent awards categories for them, if necessary.
X
X In the final round process, we perform the difficult tasks of
X reducing the remaining entries (typically about 25) down to 8 or 10
X winners. Often we are confident that the entries that make it into
X the final round are definitely better than the ones that do not
X make it. The selection of the winners out of the final round, is
X less clear cut.
X
X Sometimes a final round entry good enough to win, but is beat out
X by a similar, but slightly better entry. For this reason, it is
X sometimes worthwhile to re-enter an entry that failed to win on a
X previous year. There have been winners that lost in a previous
X year. Of course, in those cases, improving on the entry made
X the difference!
X
X More often that not, we select a small entry (usually one line), a
X strange/creative layout entry, and an entry that abuses the contest
X rules in some way.
X
X In the end, we traditionally pick one entry as 'best'. Sometimes such
X an entry simply far exceeds any of the other entry. More often, the
X 'best' is picked because it does well in a number of categories.
X
X
XANNOUNCEMENT OF WINNERS:
X
X The first announcement, occurs at a Summer Usenix conference. By
X tradition, this is done during the latter part of the UUNET/IOCCC BOF,
X just prior to the Berkeley BSD, and BSDI BOF.
X
X Winning entries will be posted in late June to the following groups:
X
X comp.lang.c comp.unix.wizards alt.sources
X
X In addition, pointers to these postings are posted to the following
X
X comp.sources.d alt.sources.d misc.misc
X comp.sources.misc
X
X Winning entries will be deposited into the uunet archives. See
X below for details.
X
X Often, winning entries are published in magazines such as "The C Users
X Journal". Winners have appeared in books ("The New Hackers Dictionary")
X and on T-Shirts.
X
X Last, but not least, winners receive international fame and flames! :-)
X
X
XFOR MORE INFORMATION:
X
X You may contact the judges by sending Email to the following address:
X
X ...!{apple,pyramid,sun,uunet}!hoptoad!judges (not the address for
X judges@toad.com submitting entries)
X
X Questions and comments about the contest are welcome.
X
X One may obtain a copy of the current rules, guidelines or mkentry
X program as well. To stream line these common requests, we request
X that you use the following subjects when making such requests:
X
X subject to request
X ------- ----------
X send rules to obtain the current IOCCC rules
X send guidelines to obtain the current IOCCC guidelines
X send mkentry to obtain the current IOCCC mkentry program
X send allinfo to obtain the current IOCCC rules,guidelines,mkentry
X
X One may also obtain the above items, we well as winners of previous
X contests, via anonymous ftp from:
X
X host: ftp.uu.net (137.39.1.9)
X user: anonymous
X pass: yourname@yourhost
X dir: pub/ioccc
X
X Often, contest rules, guidelines and winners are available from
X archive sites. Check comp.sources.unix archives, for example.
X You may also request previous winners by Email, using the judges
X Email address, though we ask that you do this as a last resort.
X
X
Xchongo <Landon Curt Noll> /\cc/\ hoptoad!chongo
XLarry Bassel {uunet,ucbvax,cbosgd}|sun!lab
END_OF_FILE
if test 22215 -ne `wc -c <'1992/guidelines'`; then
echo shar: \"'1992/guidelines'\" unpacked with wrong size!
fi
# end of '1992/guidelines'
fi
echo shar: End of archive 1 \(of 5\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 5 archives.
rm -f ark[1-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...