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, 3 of 4
Keywords: ioccc
Date: 9 Sep 92 01:41:50 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/part03

---- Cut Here and unpack ----
#!/bin/sh
# This is part 03 of ioccc.1992
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= 1992/buzzard.2.design ==============
echo "x - extracting 1992/buzzard.2.design (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.2.design &&
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
SHAR_EOF
$TOUCH -am 0908155392 1992/buzzard.2.design &&
chmod 0444 1992/buzzard.2.design ||
echo "restore of 1992/buzzard.2.design failed"
set `wc -c 1992/buzzard.2.design`;Wc_c=$1
if test "$Wc_c" != "25773"; then
	echo original size 25773, current size $Wc_c
fi
# ============= 1992/buzzard.2.hint ==============
echo "x - extracting 1992/buzzard.2.hint (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.2.hint &&
XBest Language Tool: <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    First:
X	make first
X    
X    Second:
X	echo help | cat third help.th - | first
X	cat third demo5.th | first
X    
X    Third:
X	cat third help.th - | first
X
X	Wait until Ok is printed and the type:
X	    2 3 + . cr	    <-- yes you should really type the 2 letters: cr
X
X    Forth:
X	Sorry, this is third!
X
X
XSelected notes from the author:
X
X    What it does:
X
X        first implements a relatively primitive stack machine.  How
X        primitive?  It supplies 13 visible primitives: 3 arithmetic,
X        1 comparison, 2 memory-access, 2 character I/O, 3 primitives
X        for defining new words, 1 tokenizing, and 1 special stack
X        operation.  (There are also three internal operations for
X        the stack machine: 'push this integer', 'call this code',
X        and 'compile a call to this code'.)
X
X        It is very difficult to accomplish anything with this set
X        of primitives, but they do have an interesting property.
X
X        This--what this interesting property is, or in other words
X        what first is good for--is the major obfuscation; there are
X        also minor source obfuscations, as well as some design tricks
X        that are effectively obfuscations.  Details on the obfuscations
X        are below, and the interesting property is discussed much
X        further down.
X
X
X    How to run it:
X
X        first expects you to first enter the names of the 13 primitives,
X        separated by whitespace--it doesn't care what you name them, but
X        if all the names aren't unique, you won't be able to use some of
X        them.  After this you may type any sequence of valid first input.
X        Valid first input is defined as any sequence of whitespace-delimited
X        tokens which consist of primitives, new words you've defined, and
X        integers (as parsed by "%d").  Invalid input behaves unpredictably,
X        but gives no warning messages.  A sample program, demo1.1st, is
X        included, but it only works on ASCII systems.
X
X        Do not expect to be able to do anything interesting with first.
X
X        To do something interesting, you need to feed first the file
X        third first.  In unix, you can do
X
X                % cat third help.th - | first
X
X        to do this.  Hopefully most operating systems will provide a
X        way to do this.  It may take some time for this to complete
X	(I seem to remember it taking several minutes on an 8086 PC);
X        THIRD will prompt you when it is finished.  The file third has
X        not been obfuscated, due to sheer kindness on the author's part.
X
X        For more information on what you can do once you've piped
X        THIRD into first, type 'help' and consult FORTH manuals for
X        further reference.  Six sample THIRD programs are included
X	in the files demo[1-6].th.  buzzard.2.README has more
X	information.
X
X        Keep in mind that you are still running first, and
X        are for the most part limited by first's tokenizer
X        (notably, unknown words will attempt to be parsed as
X        integers.)  It is possible to build a new parser that
X        parses by hand, reading a single character at a time;
X	however, such a parser cannot easily use the existing
X	dictionary, and so would have to implement its own,
X	thus requiring reimplementing all of first and third
X	a second time--I did not care to tackle this project.
X
X
X    Compiling:
X
X        first is reasonably portable.  You may need to adjust the
X        size of the buffers on smaller machines; m[] needs to be
X        at least 2000 long, though.
X
X        I say first is portable mainly because it uses native types.
X        Unlike FORTH, which traditionally allows byte and multi-byte
X        operations, all operations are performed on C 'int's.  That
X        means first code is only as portable as the same code would
X        be in C.  As in C, the result of dividing -1 by 2 is machine
X        (or rather compiler) dependent.
X
X    How is first obfuscated?
X
X        first is obfuscated in several ways.  Some minor obfuscations
X        like &w[&m[1]][s] for s+m[w+1] were in the original source
X	but are no longer because, apparently, ANSI doesn't allow it
X	(gcc -ansi -pedantic doesn't mind it, though.)
X	Other related obfuscations are still present.  The top of the
X	stack is cached in a variable, which increases performance
X	massively if the compiler can figure out to keep it in a register;
X	it also obfuscates the code.  (Unfortunately, the top of stack
X	is a global variable and neither gcc nor most bundled compilers
X	seem to register allocate it.)
X	
X        More significant are the design obfuscations.  m[0] is the
X        "dictionary pointer", used when compiling words, and m[1] is
X        the return stack index.  Both are used as integer offsets into
X        m.  Both are kept in m, instead of as separate pointers,
X        because they are then accessible to first programs, which is a
X        crucial property of first.  Similarly the way words are stored
X        in the dictionary is not obvious, so it can be difficult to
X        follow exactly what the compiler words are doing.
X
X        Assuming you've waded through all that, you still have
X        to penetrate the most significant obfuscation.  Traditionally,
X        the question is whether a reader can answer the question "what
X        will this do when I run it".  A reader who has deciphered first
X        to this point may think they know the answer to this question,
X        but they may not know the answer to the more important question,
X        "what will this program do when given the right input?"  FORTH
X        afficianados, and especially FORTH implementors, may recognize
X        the similarity of the internal compiler format to many FORTH
X        interal representations, and, being aware that FORTH interpreters
X        can often by self-compiling, may be suspicious that this program
X        can compile FORTH, or a significant subset of it, or at least be
X        capable of doing so if fed the right input.  Of course, the name
X        "THIRD" should be a dead giveaway, if the name "first" wasn't.
X        (These numbers were largely chosed because they were five letters
X        long, like "FORTH", and would not require truncation to five
X        letters, which would be a dead giveaway.  Besides, THIRD represents
X        a step backwards, in more ways than one.)
X
X
X    What exactly is first, then?
X
X    first is a tiny interpreter which implements a sufficient
X    pseudo-subset of FORTH to allow it to bootstrap a relatively
X    complete version of FORTH (based loosely on forth79), which
X    I call THIRD.  Complete relative to what, I'm not sure.
X
X    I believe first is close to the smallest amount of code possible
X    to get this effect *using forth-style primitives*, and still have
X    some efficiency (it is possible to get by without multiplication
X    if you have addition, obviously).  In the design file, design,
X    I give a justification for why each primitive in first was included.
X
X    THIRD is sorta slow, because first has so few primitives that
X    many things that are primitives in FORTH (like swap) take a
X    significant amount of time in THIRD.
X
X    When you get the 'Ok.' message from third, try out some sample
X    FORTH code (first has no way of knowing if keyboard input is
X    waiting, so it can't actually prompt you in a normal way.  It
X    only prints 'Ok.' after you define a word).
X
X        2 3 + . cr    ( add 2 and 3, and print it and a newline.)
X
X    and THIRD responds
X
X        5
X
X    Now try:
X
X        : test 11 1 do i . loop cr ;
X        test
X
X    and THIRD responds
X
X        1 2 3 4 5 6 7 8 9 10
X
X
X    When in THIRD, you can see how much space you're currently
X    using by typing
X
X        here .
X
X    The number THIRD replies is the number of machine words (ints)
X    that the dictionary (the first code) takes up, plus the
X    512 ints for the return stack.  If you compile the basic
X    THIRD system without the help word (strings take up one
X    int per character in the string!), you should find that
X    you're using around 1000 ints (plus the return stack).
X
X    Thus THIRD gives you a relatively complete FORTH system in
X    less than 700 chars of C source + about 1000 ints of
X    memory--and it's portable too (you could copy over the
X    THIRD memory dump to another machine, in theory).  If the
X    above numbers seem to you to be mixing apples and oranges
X    (C source and compiled THIRD code), note that you should
X    in theory be able to stick the compiled THIRD code into
X    the C source.
X
X
X    Software Construction Company gets credit for rekindling
X    my interest in FORTH and thus indirectly inspiring me
X    to write this program.
SHAR_EOF
$TOUCH -am 0908160292 1992/buzzard.2.hint &&
chmod 0444 1992/buzzard.2.hint ||
echo "restore of 1992/buzzard.2.hint failed"
set `wc -c 1992/buzzard.2.hint`;Wc_c=$1
if test "$Wc_c" != "8915"; then
	echo original size 8915, current size $Wc_c
fi
# ============= 1992/buzzard.2.orig.c ==============
echo "x - extracting 1992/buzzard.2.orig.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.2.orig.c &&
X#define c 0 [m] ++ [m] =
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(x++[m]){
X	z 5:	for(w=scanf("%s",s)<1?exit(0):L;strcmp(s,&w[&m[1]][s]);w=m[w]);
X		w-1 ? r(w+2) : (c 2,c atoi(s))
X	z 12:	I=1[m]--[m]
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=I++[m]
X	z 8:	f= *S --- f
X	z 2:	m[++1[m]]=I;
X		I=x
X	z 11:	f=0>f
X	z 4:	*m-=2;c 2
X	z 6:	f=f[m]
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 0817110092 1992/buzzard.2.orig.c &&
chmod 0444 1992/buzzard.2.orig.c ||
echo "restore of 1992/buzzard.2.orig.c failed"
set `wc -c 1992/buzzard.2.orig.c`;Wc_c=$1
if test "$Wc_c" != "794"; then
	echo original size 794, current size $Wc_c
fi
# ============= 1992/demo1.1st ==============
echo "x - extracting 1992/demo1.1st (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/demo1.1st &&
X: immediate _read @ ! - * / <0 exit echo key _pick
X
X: show echo echo echo echo exit
X: all show show show show echo exit
X
X: doit immediate
X    10 33 100 108 114 111 87
X    32 111 108 108 101 72
X    all
Xexit
X
Xdoit
SHAR_EOF
$TOUCH -am 0817110092 1992/demo1.1st &&
chmod 0444 1992/demo1.1st ||
echo "restore of 1992/demo1.1st failed"
set `wc -c 1992/demo1.1st`;Wc_c=$1
if test "$Wc_c" != "212"; then
	echo original size 212, current size $Wc_c
fi
# ============= 1992/demo1.th ==============
echo "x - extracting 1992/demo1.th (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/demo1.th &&
X: demo1 " Hello world!
X" ;
X
Xdemo1
SHAR_EOF
$TOUCH -am 0817110092 1992/demo1.th &&
chmod 0444 1992/demo1.th ||
echo "restore of 1992/demo1.th failed"
set `wc -c 1992/demo1.th`;Wc_c=$1
if test "$Wc_c" != "34"; then
	echo original size 34, current size $Wc_c
fi
# ============= 1992/demo2.th ==============
echo "x - extracting 1992/demo2.th (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/demo2.th &&
X: demo2 
X
X	10 0		( iterate from 0 stopping before 10 )
X	do
X	    i .  	( print the loop counter )
X	loop
X	cr		( add a newline )
X;
X
Xdemo2
SHAR_EOF
$TOUCH -am 0817110092 1992/demo2.th &&
chmod 0444 1992/demo2.th ||
echo "restore of 1992/demo2.th failed"
set `wc -c 1992/demo2.th`;Wc_c=$1
if test "$Wc_c" != "135"; then
	echo original size 135, current size $Wc_c
fi
# ============= 1992/demo3.th ==============
echo "x - extracting 1992/demo3.th (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/demo3.th &&
X: printfour
X
X	dup		( save the number on top of the stack )
X	4 =		( compare it to four )
X	if
X	  " forth "	( output a string for it )
X	  drop		( and delete the saved value )
X        else
X	  .
X	endif
X;
X
X: demo3 10 0 do i printfour loop cr ;
X
Xdemo3
SHAR_EOF
$TOUCH -am 0817110092 1992/demo3.th &&
chmod 0444 1992/demo3.th ||
echo "restore of 1992/demo3.th failed"
set `wc -c 1992/demo3.th`;Wc_c=$1
if test "$Wc_c" != "245"; then
	echo original size 245, current size $Wc_c
fi
# ============= 1992/demo4.th ==============
echo "x - extracting 1992/demo4.th (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/demo4.th &&
X( compute factorial recursively )
X( take x as input, return x! and x as output )
X
X: fact-help
X
X  dup if
X    1 -			( leave x-1 on top )
X    fact-help		( leave x-1, [x-1]! )
X    1 +			( leave x, [x-1]!, x )
X    swap over swap	( leave [x-1]!, x, x )
X    *			( into x!, x )
X    swap		( into x, x! )
X  else
X    1 swap
X  then
X;
X
X: fact
X
X  fact-help
X  drop
X
X;
X
X: demo4
X  " 4 factorial is: " 4 fact . cr
X  " 6 factorial is: " 6 fact . cr
X;
X
Xdemo4
SHAR_EOF
$TOUCH -am 0817110092 1992/demo4.th &&
chmod 0444 1992/demo4.th ||
echo "restore of 1992/demo4.th failed"
set `wc -c 1992/demo4.th`;Wc_c=$1
if test "$Wc_c" != "439"; then
	echo original size 439, current size $Wc_c
fi
# ============= 1992/demo5.th ==============
echo "x - extracting 1992/demo5.th (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/demo5.th &&
X( recursive factorial.  given x on top, followed by )
X( an "accumulator" containing the product except for x! )
X
X: fact-help2
X
X  dup if
X    swap over swap
X    *
X    swap 1 -
X    fact-help2
X  then
X;
X
X: fact
X
X  1 swap
X  fact-help2
X  drop
X;
X
X: demo5
X
X  " The factorial of 3 is: " 3 fact . cr
X  " The factorial of 5 is: " 5 fact . cr
X;
X
Xdemo5
SHAR_EOF
$TOUCH -am 0817110092 1992/demo5.th &&
chmod 0444 1992/demo5.th ||
echo "restore of 1992/demo5.th failed"
set `wc -c 1992/demo5.th`;Wc_c=$1
if test "$Wc_c" != "339"; then
	echo original size 339, current size $Wc_c
fi
# ============= 1992/demo6.th ==============
echo "x - extracting 1992/demo6.th (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/demo6.th &&
X: foobar
X  2
X  [ 2 ,		  ( '[' turns the compiler off, allowing us to execute code )
X    1 1 1 + + ,   ( and we compile in-line a 2 and a three )
X		  ( the '2' means 'push the number following this' )
X  ]
X  + . cr
X;
X
Xfoobar
X
X: 'foobar ' foobar ;    ( ' can only be run inside the compiler )
X			( ' leaves the address of the following word
X			    on the stack )
X
X'foobar . cr
X
X'foobar dump
SHAR_EOF
$TOUCH -am 0817110092 1992/demo6.th &&
chmod 0444 1992/demo6.th ||
echo "restore of 1992/demo6.th failed"
set `wc -c 1992/demo6.th`;Wc_c=$1
if test "$Wc_c" != "388"; then
	echo original size 388, current size $Wc_c
fi
# ============= 1992/gson.c ==============
echo "x - extracting 1992/gson.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/gson.c &&
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();}
SHAR_EOF
$TOUCH -am 0817110092 1992/gson.c &&
chmod 0444 1992/gson.c ||
echo "restore of 1992/gson.c failed"
set `wc -c 1992/gson.c`;Wc_c=$1
if test "$Wc_c" != "1513"; then
	echo original size 1513, current size $Wc_c
fi
# ============= 1992/gson.hint ==============
echo "x - extracting 1992/gson.hint (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/gson.hint &&
XMost Humorous Output: <gson@niksula.hut.fi> Andreas Gustafsson
X
X	Andreas Gustafsson
X	Helsinki University of Technology
X	Arentikuja 1 D 305			(home address)
X	00410 Helsinki
X	FINLAND
X
X
XJudges' comments:
X
X    To make:
X	make ag
X    
X    Determine where your system dictionary is located.  You may find
X    it located in one of the following places:
X
X	    /usr/dict/words
X	    /usr/share/lib/spell/words
X	    /usr/ucblib/dict/words
X	    /dev/null			<-- for machines with nothing to say
X    
X    Then using the proper dictionary:
X
X        ag free software foundation	< /usr/dict/words
X        ag obfuscated c contest		< /usr/dict/words
X        ag unix international		< /usr/dict/words
X	ag george bush			< /usr/dict/words
X	ag bill clinton			< /usr/dict/words
X	ag ross perot			< /usr/dict/words
X	ag paul e tsongas		< /usr/dict/words
X
X    Recently some newspapers printed amusing anagrams of one of the
X    names listed above.  Run this program to find the anagrams they
X    weren't allowed to print!
X
X
XSelected notes from the author:
X
X    The name of the game:
X    
X    AG is short for either Anagram Generator or simply AnaGram.
X    It might also be construed to mean Alphabet Game, and by pure
X    coincidence it happens to be the author's initials.
X    
X    
X    What it does:
X    
X    AG takes one or more words as arguments, and tries to find
X    anagrams of those words, i.e. words or sentences containing
X    exactly the same letters.
X    
X    
X    How to use it:
X    
X    To run AG, you need a dictionary file consisting of distinct words
X    in the natural language of your choice, one word on each line.  If
X    your machine doesn't have one already, you can make your own
X    dictionary by concatenating a few hundred of your favourite Usenet
X    articles and piping them through the following obfuscated shell
X    script:
X    
X        #!/bin/sh
X        z=a-z];tr [A-Z\] \[$z|sed s/[\^$z[\^$z*/_/g|tr _ \\012|grep ..|sort -u
X    
X    Using articles from alt.folklore.computers is likely to make
X    a more professional-looking dictionary than rec.arts.erotica.
X    
X    AG must be run with the dictionary file as standard input.
X    
X    Because anagrams consisting of just a few words are generally more
X    meaningful than those consisting of dozens of very short words, the
X    number of words in the anagrams is limited to 3 by default.  This
X    limit can be changed using a numeric command line option, as in
X    "ag -4 international obfuscated c code contest </usr/dict/words".
X    
X    Bugs:
X    
X      - There is no error checking
X      - Standard input must be seekable, so you can't pipe the dictionary
X        into AG.
X      - The input sentence and each line in the dictionary may contain
X        at most 32 distinct letters, and each letter may occur at most 15
X        times.
X      - Words in the dictionary may be at most 255 bytes long
X      - AG cannot handle characters that sign-extend to negative values
X      - Although AG works on both 16-bit and 32-bit machines, 
X        the size of the problems it can solve is severely limited 
X        on machines that limit the stack size to 64k or less.
X    
X    
X    Obfuscatory notes:
X    
X    As you can see, AG takes advantage of the new '92 whitespace rules to
X    achieve a clear, readable, self-documenting layout.  The identifiers
X    have been chosen in a way appropriate for an alphabet game, and common
X    sources of bugs such as goto statements and malloc/free have been
X    eliminated.  As AG also refrains from abusing the preprocessor, it
X    doesn't really have much to offer in terms of "surface obfuscation".
X    Instead, it tries to achieve both its speed and its obscurity through a
X    careful choice of algorithms.  Some of the finer points of those
X    algorithms are outlined in the rot-13 encoded spoiler below.
X    
X    How it works:  (ROT13 to read)
X    
X    Urer sbyybjf n qrfpevcgvba bs fbzr bs gur qngn fgehpgherf naq
X    nytbevguzf hfrq ol NT.  Vg vf ol ab zrnaf pbzcyrgr, ohg vg znl uryc
X    lbh trg na vqrn nobhg gur trareny cevapvcyrf.
X    
X    --
X    
X    Vagreanyyl, NT ercerfragf jbeqf naq fragraprf nf neenlf bs 32
X    4-ovg vagrtre ryrzragf.  Rnpu ryrzrag ercerfragf gur ahzore bs
X    gvzrf n yrggre bpphef va gur jbeq/fragrapr.  Gurer ner 32 ryrzragf
X    orpnhfr 32 vf n pbairavrag cbjre bs gjb ynetre guna gur ahzore bs
X    yrggref va zbfg jrfgrea nycunorgf, naq gur ryrzragf ner 4 ovgf
X    rnpu orpnhfr gur fnzr yrggre vf hayvxryl gb bpphe zber guna 15
X    gvzrf va n cenpgvpny nantenz trarengvba ceboyrz.
X    
X    Gurfr 32*4-ovg neenlf ner npghnyyl fgberq va zrzbel va n
X    "ovg-genafcbfrq" sbezng, nf neenlf bs sbhe "ybat" inyhrf.  Vg vf
X    nffhzrq gung n "ybat" vf ng yrnfg 32 ovgf.  Gur svefg 4-ovg yrggre
X    pbhag vf sbezrq ol gur yrnfg fvtavsvpnag (2^0) ovg va rnpu bs gur
X    sbhe ybatf, gur arkg bar vf sbezrq ol gur 2^1 ovgf, rgp.
X    
X    Guvf fgbentr sbezng znxrf vg cbffvoyr gb nqq be fhogenpg gjb fhpu
X    irpgbef bs 32 4-ovg inyhrf va cnenyyry ol fvzhyngvat n frg bs 32
X    ovanel shyy nqqref va fbsgjner hfvat ovgjvfr ybtvpny bcrengvbaf.
X    R.t., nyy gur YFO:f bs gur erfhyg ner sbezrq va cnenyyry ol gnxvat
X    gur rkpyhfvir BE bs gur YFO:f va rnpu fhzznaq, naq 32 pneel ovgf
X    ner sbezrq va cnenyyry va n fvzvyne jnl hfvat n ybtvpny NAQ.
X    Guhf, 32 vaqrcraqrag 4-ovg nqqvgvbaf pna or cresbezrq ol whfg sbhe
X    vgrengvbaf bs n ybbc pbagnvavat fbzr 32-ovg ovgjvfr ybtvpny
X    bcrengvbaf, ohg ab nevguzrgvp bcrengvbaf bgure guna gubfr vzcyvrq
X    ol neenl vaqrkvat.
X    
X    Fhogenpgvba jbexf fvzvyneyl, naq va snpg NT bayl vzcyrzragf
X    fhogenpgvba qverpgyl, unaqyvat nqqvgvba ol zrnaf bs gur vqragvgl
X    n+o = n-(0-o).
X    
X    Va nqqvgvba gb guvf 32*4-ovg ercerfragngvba, NT nyfb sbezf n fb-pnyyrq
X    "fvtangher" gung vf gur ovgjvfr BE bs gur sbhe ybatf, juvpu vf
X    rdhvinyrag gb fnlvat gung gur fvtangher bs n jbeq pbagnvaf n ybtvpny 1
X    va gur ovg cbfvgvbaf pbeerfcbaqvat gb yrggref bppheevat ng yrnfg bapr
X    va gung jbeq.
X    
X    Gur svefg guvat NT qbrf vf gb pbafgehpg n ybbxhc gnoyr bs 256
X    ybatf, bar sbe rnpu 8-ovg punenpgre inyhr.  Gur ragel sbe n
X    punenpgre jvyy or mreb vs gung punenpgre qbrfa'g nccrne va gur
X    fragrapr tvira ba gur pbzznaq yvar, be vg jvyy unir n fvatyr ovg
X    frg vs gur punenpgre qbrf nccrne va gur fragrapr.  Ol nqqvat
X    gbtrgure gur ovg znfxf sbe nyy gur yrggref va gur vachg fragrapr
X    hfvat gur genafcbfr nqqvgvba zrgubq qrfpevorq nobir, NT sbezf gur
X    32*4 ovg neenl ercerfragngvba bs gur vachg fragrapr.
X    
X    Gur arkg npgvba cresbezrq vf ernqvat gur qvpgvbanel.  Gubfr jbeqf gung
X    pbagnva yrggref abg va gur vachg fragrapr ner vzzrqvngryl qvfpneqrq.
X    Jbeqf pbagnvavat gur evtug yrggref ohg va rkprffvir ahzoref ner
X    ryvzvangrq va n frcnengr purpx vaibyivat gur 32*4 ovg neenl.
X    
X    Gur erznvavat jbeqf, juvpu jvyy or ersreerq gb nf "pnaqvqngr jbeqf",
X    ner fgberq va 32*4-ovg ercerfragngvba, gbtrgure jvgu gurve fvtangherf 
X    naq bssfrgf vagb gur qvpgvbanel svyr fb gung gur cynva-grkg irefvba bs
X    n jbeq pna yngre or sbhaq sbe cevagvat.  Guvf vasbezngvba vf xrcg va n
X    ybpny "fgehpg" va gur qvpgvbanel-ernqvat shapgvba, naq zrzbel vf
X    nyybpngrq sbe rnpu pnaqvqngr jbeq fvzcyl ol znxvat nabgure erphefvir
X    pnyy gb gung shapgvba.
X    
X    Rnpu fgehpg fb nyybpngrq vf yvaxrq vagb n svkrq-fvmr unfu gnoyr bs
X    4096 ragevrf vaqrkrq ol gur 12 ybj ovgf bs gur jbeq'f fvtangher. 
X    Jura gur qvpgvbanel-ernqvat shapgvba rapbhagref raq-bs-svyr, nyy gur
X    pnaqvqngr jbeqf unir orra fgberq va arfgrq npgvingvba erpbeqf ba gur
X    fgnpx, npprffvoyr guebhtu gur unfu gnoyr.
X    
X    Trarengvat gur nantenzf vf gura qbar ol genirefvat gur unfu gnoyr naq
X    fhogenpgvat gur yrggref bs rnpu jbeq va gur unfu gnoyr sebz gur
X    "pheerag fragrapr", juvpu vavgvnyyl vf gur fragrapr tvira ba gur
X    pbzznaq yvar.
X    
X    Gur fhogenpgvba vf cresbezrq va cnenyyry ba gur 4-ovg yrggre pbhagf
X    nf qrfpevorq nobir, naq vs nyy 32 erfhygf ner mreb, na nantenz unf
X    orra sbhaq.  Vs gur erfhyg vf artngvir sbe bar be zber bs gur yrggref
X    (nf vaqvpngrq ol bar be zber "1" va n irpgbe bs 32 obeebj ovgf
X    erghearq ol gur fhogenpgvba ebhgvar), gur jbeq qvq abg zngpu gur
X    pheerag fragrapr naq vf vtaberq.  Svanyyl, vs gur erfhyg pbagnvarq
X    bayl abaartngvir yrggre pbhagf, jr unir sbhaq n cnegvny nantenz: 
X    n jbeq pbagnvavat fbzr, ohg abg nyy, bs gur yrggref va gur pheerag
X    fragrapr.  Va guvf pnfr jr erphefviryl gel gb svaq na nantenz bs gur
X    erznvavat yrggref.  Gur qrcgu bs gur erphefvba vf yvzvgrq gb gur
X    znkvzhz ahzore bs jbeqf va gur nantenz, nf fcrpvsvrq ol gur hfre.
X    
X    Jura gur qrrcrfg erphefvba yriry unf orra ernpurq, na bcgvzvmngvba pna
X    or nccyvrq: orpnhfr ab shegure erphefvba jvyy or qbar, gurer vf ab
X    arrq gb ybbx sbe cnegvny nantenzf, naq gurersber NT bayl arrqf gb
X    purpx sbe jbeqf gung pbagnva rknpgyl gur fnzr yrggref nf gur pheerag
X    fragrapr.  Gubfr jbeqf pna or sbhaq fvzcyl ol vaqrkvat gur unfu gnoyr
X    jvgu gur fvtangher bs gur pheerag fragrapr.
X    
X    Rira jura abg ba gur qrrcrfg erphefvba yriry, NT trarenyyl nibvqf
X    rknzvavat nyy gur ragevrf bs gur unfu gnoyr.  Gur vqrn vf gung jr ner
X    abg vagrerfgrq va unfu ohpxrgf jubfr jbeqf pbagnva nal yrggref abg
X    va gur pheerag fragrapr; gurfr ohpxrgf ner rknpgyl gubfr jubfr vaqrk
X    unf n ybtvpny bar va n ovg cbfvgvba jurer gur fvtangher bs gur pheerag
X    fragrapr unf n mreb.  Chg nabgure jnl, jr jnag gb ybbc guebhtu bayl
X    gubfr unfu ohpxrg vaqvprf "v" gung pbagnva mrebrf va nyy gur ovg
X    cbfvgvbaf jurer gur fvtangher "f" bs gur pheerag fragrapr pbagnvaf
X    n mreb; guvf pna or rkcerffrq va P nf (v & ~f == 0).
X    
X    Vg vf cbffvoyr gb ybbc guebhtu nyy fhpu ahzoref va na rssvpvrag jnl ol
X    gnxvat nqinagntr bs pregnva cebcregvrf bs ovanel nevguzrgvp: ol
X    sbepvat gur ovgf pbeerfcbaqvat gb mrebrf va "f" gb barf, jr pna znxr
X    gur pneevrf trarengrq va vaperzragvat "v" cebcntngr fgenvtug npebff
X    gubfr ovgf gung fubhyq erznva mreb.  Sbe rknzcyr, gur sbyybjvat
X    cebtenz cevagf nyy gubfr 16-ovg vagrtref gung pbagnva mrebrf va nyy
X    rira ovg cbfvgvbaf:
X    
X        znva(){vag v=0,f=0kNNNN;qb{cevags("%04k\g",v);}juvyr(v=((v|~f)+1)&f);}
X    
X    NT hfrf n fvzvyne zrgubq ohg jbexf va gur bccbfvgr qverpgvba, svaqvat
X    gur arkg ybjre inyhr jvgu mrebrf va tvira ovg cbfvgvbaf ol cebcntngvat
X    obeebjf npebff gubfr ovgf.  Fbzr nqqvgvbany nqwhfgzragf ner znqr
X    gb gur unfu gnoyr vaqrk jura vavgvngvat n erphefvir frnepu, hfvat
X    fvzvyne ovg-gjvqqyvat grpuavdhrf.
X    
X    Jurarire na nantenz unf orra sbhaq, vg vf cevagrq ol genirefvat n
X    yvaxrq yvfg sbezrq ol fgehpgf va gur npgvingvba erpbeqf bs gur
X    erphefvir vaibpngvbaf bs gur frnepu shapgvba, frrxvat gb gur ortvaavat
X    bs gur jbeq zngpurq ol gung vaibpngvba, naq pbclvat gur punenpgref bs
X    gur jbeq qverpgyl sebz fgnaqneq vachg gb fgnaqneq bhgchg.
SHAR_EOF
$TOUCH -am 0908160292 1992/gson.hint &&
chmod 0444 1992/gson.hint ||
echo "restore of 1992/gson.hint failed"
set `wc -c 1992/gson.hint`;Wc_c=$1
if test "$Wc_c" != "10891"; then
	echo original size 10891, current size $Wc_c
fi
# ============= 1992/help.th ==============
echo "x - extracting 1992/help.th (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/help.th &&
X: help key  ( flush the carriage return form the input buffer )
X
X" The following are the standard known words; words marked with (*) are
Ximmediate words, which cannot be used from command mode, but only in
Xword definitions.  Words marked by (**) declare new words, so are always
Xfollowed by the new word.
X
X	! @		fetch, store
X	+ - * / mod	standard arithmetic operations
X	= < > <= >=	standard comparison operations
X
X	not		boolean not of top of stack
X	logical		turn top of stack into 0 or 1
X
X	dup over	duplicate the top of stack or second of stack
X	swap drop	reverse top two elements or drop topmost
X
X	inc dec		increment/decrement the value at address from stack
X	add		add a value from 2nd of stack into address from top
X
X	echo key	output character from, or input to, top of stack
X	. #		print out number on top of stack without/with cr
X	cr		print a carriage return
X
X[more]" key
X" (**)	var		declare variable with initial value taken from stack
X(**)	constant	declare constant with initial value taken from stack
X(**)	array		declare an array with size taken from stack
X
X(*)	if...else...then	FORTH branching construct
X(*)	do...loop		FORTH looping construct
X	i j			loop values (not variables)
X
X	print		print the string pointed to on screen
X
X(*)(**) :		declare a new THIRD word
X(*)	<build does>	declare a data types compile-time and run-time
X(*)	;		terminate a word definition
X
X[more]" key
X" Advanced words:
X	here		current location in dictionary
X	h		pointer into dictionary
X	r		pointer to return stack
X	fromr tor	pop a value from or to the return stack
X
X	,		write the top of stack to dictionary
X	'		store the address of the following word on the stack
X	allot		leave space on the dictionary
X
X	::		compile a ':' header
X	[		switch into command mode
X	]		continue doing : definitions
X" ;
SHAR_EOF
$TOUCH -am 0817110092 1992/help.th &&
chmod 0444 1992/help.th ||
echo "restore of 1992/help.th failed"
set `wc -c 1992/help.th`;Wc_c=$1
if test "$Wc_c" != "1774"; then
	echo original size 1774, current size $Wc_c
fi
# ============= 1992/imc.c ==============
echo "x - extracting 1992/imc.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1992/imc.c &&
X#include		     <stdio.h> 
X#include		     <malloc.h> 
X#define			  ext(a) (exit(a),0)
X#define I		  " .:\';+<?F7RQ&%#*"
X#define a			"%s?\n"
X#define n			"0?\n"
X#define C			double	
X#define o			 char
X#define l			 long
X#define L			sscanf
X#define i			stderr
X#define e			stdout
X#define r		       ext   (1)
X#define s(O,B)	   L(++J,O,&B)!=1&&c>++q&&L(v[q],O,&B)!=1&&--q
X#define F(U,S,C,A) t=0,*++J&&(t=L(J,U,&C,&A)),(!t&&c>++q&&!(t=L(v[q],U,\
X		   &C,&A)))?--q:(t<2&&c>++q&&!(t=L(v[q],S,&A))&&--q
X#define T(E)		(s("%d",E),E||(fputs(n,i),r))
X#define d(C,c)		  (F("%lg,%lg","%lg",C,c)))
X#define O	   (F("%d,%d","%d",N,U),(N&&U)||(fputs(n,i),r)))
X#define D		      (s("%lg",f))
X#define E			  putc
X					       C
X						G=0,
X						R
X					     =0,Q,H
X					    ,M,P,z,S
X					     =0,x=0
X				 ,        f=0;l b,j=0,	      k
X				  =128,K=1,V,B=0,Y,m=128,p=0,N
X				 =768,U=768,h[]={0x59A66A95,256
X			     ,192,1,6912,1,0,0},t,A=0,W=0,Z=63,X=23
X			    ;o*J,_;main(c,v)l c;o**v;{l q=1;for(;;q<
X		  c	   ?(((J=v[q])[0]&&J[0]<48&&J++,((_= *J)<99||
X		_/2==	   '2'||(_-1)/3=='\"'||_==107||_/05*2==','||_
X	      >0x074)?(   fprintf(i,a,v[q]),r):_>0152?(_/4>27?(_&1?(
X	     O,Z=N,X=U):  (W++,N=Z,U=X)):_&1?T(K):T(k)):_>103?(d(G,
X	R    ),j=1):_&1? d(S,x):D,q++),q--,main(c-q,v+q)):A==0?(A=
X  1,f||(f=N/4.),b=(((N-1)&017)<8),q=(((N+7)>>3)+b)*U,(J=malloc(q)
X  )||(perror("malloc"),r),S-=(N/2)/f,x+=(U/2)/f):A==1?(B<U?(A=2,V
X	=    0,Q=x-B/f,j ||(R=Q),W&&E('\n',e),E(46,i)):(W&&E('\n',
X	     e),E('\n',i  ),h[1]=N,h[2]=U,h[4]=q,W||(fwrite(h,1,32,
X	      e),fwrite   (J,1,q,e)),free(J),ext(0))):A==2?(V<N?(j?
X		(H=V/f	   +S,M=Q):(G=V/f+S,H=M=0),Y=0,A=03):((m&0x80
X		   )	   ||(m=0x80,p++),b&&(J[p++]=0),A=1,B++)):((Y
X			    <k&&(P=H*H)+(z=M*M)<4.)?(M=2*H*M+R,H=P-z
X			     +G,Y++):(W&&E(I[0x0f*(Y&K)/K],e),Y&K?J
X			         [p]&=~m:(J[p]|=m),(m>>=1)||/*/
X				  (m=128,u--),A==6?ext(1):B<u
X				 .	  e=3,l=2*c*/(       m
X					     =0x80,
X					    p++),V++
X					     ,A=0x2
X						)
X						));
X					       }
SHAR_EOF
$TOUCH -am 0817110392 1992/imc.c &&
chmod 0444 1992/imc.c ||
echo "restore of 1992/imc.c failed"
set `wc -c 1992/imc.c`;Wc_c=$1
if test "$Wc_c" != "1965"; then
	echo original size 1965, current size $Wc_c
fi
echo "End of part 3, continue with part 4"
exit 0
-- 
For a good prime, call:  391581 * 2^216193 - 1
Xref: sparky comp.lang.c:13351 comp.sources.d:1250 comp.unix.wizards:3850 alt.sources:2020 misc.misc:3275