home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume32 / ioccc.1992 / part01 next >
Text File  |  1992-09-11  |  56KB  |  1,497 lines

  1. Newsgroups: comp.sources.misc
  2. From: chongo@toad.com (Landon Curt Noll)
  3. Subject:  v32i028:  ioccc.1992 - 1992 International Obfuscated C Code Contest winners, Part01/05
  4. Message-ID: <csm-v32i028=ioccc.1992.103926@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: fced55eeed9eefb316aacae723a465d0
  6. Date: Thu, 10 Sep 1992 15:40:38 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: chongo@toad.com (Landon Curt Noll)
  10. Posting-number: Volume 32, Issue 28
  11. Archive-name: ioccc.1992/part01
  12. Environment: C
  13.  
  14. Enclosed is the first of a 5 part shar file containing the winners of
  15. the 1992 International Obfuscated C Code Contest.
  16.  
  17. First, we congratulate the winners for doing a fine job.  Their efforts
  18. and feedback have resulted another good year for the contest.
  19.  
  20. Second, the 1993 contest will not open until early March 1993.  The
  21. rules are expected to be very similar to the 1992 rules, though the
  22. input format will change slightly.  Please wait for the 1993 rules
  23. to be posted before submitting 1993 entries.
  24.  
  25. Third, an International Obfuscated Perl contest is being considered.
  26. Larry Wall and Landon Curt Noll plan to formulate the contest rules
  27. (and a contest name) sometime this year.  Watch comp.lang.perl for
  28. details.  Send contest ideas (but not entries!) to chongo@toad.com.
  29.  
  30. Last, we would like to make an apology to the 1992 winners and to the
  31. net for the delay in posting of these results.  The poster of this
  32. article (chongo) went on vacation, held extended discussions with
  33. several of the contest winners and attempted to deal with one entry
  34. that appears to conflict with US export regulations.
  35.  
  36. If you find problems with some of the contest entries, or find typos
  37. in our notes, please send ->PATCH FILES OR COMPLETE FILES<- containing
  38. the corrections to:
  39.  
  40.     judges@toad.com   -or-   ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
  41.  
  42. chongo <Landon Curt Noll> /\cc/\        hoptoad!chongo
  43. Larry Bassel                            {uunet,ucbvax,cbosgd}|sun!lab
  44.  
  45. p.s. previous winners are available on ftp.uu.net via anonymous ftp
  46.      under the directory ~/pub/ioccc.  Any 'patches' to the 1992 winners
  47.      will be deposited there in a few months.
  48.  
  49. =-=
  50.  
  51.  Send comments, questions, bugs to: 
  52.   
  53.       judges@toad.com   -or-   ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
  54.    
  55.  You are strongly encouraged to read the new contest rules before
  56.  sending any entries.  The rules, and sometimes the contest Email
  57.  address itself, change over time.  A valid entry one year may
  58.  be rejected in a later year due to changes in the rules.  The typical
  59.  start date for a contest is early March.  The typical end date for a
  60.  contest is early May.
  61.    
  62.  The contest rules are posted to comp.unix.wizards, comp.lang.c,
  63.  misc.misc, alt.sources and comp.sources.d.  If you do not have access 
  64.  to these groups, or if you missed the early March posting, you may 
  65.  request a copy from the judges, via Email, at the address above.
  66.    
  67. ---- Cut Here and unpack ----
  68. #! /bin/sh
  69. # This is a shell archive.  Remove anything before this line, then feed it
  70. # into a shell via "sh file" or similar.  To overwrite existing files,
  71. # type "sh file -c".
  72. # Contents:  1992 1992/buzzard.2.design 1992/gson.c 1992/guidelines
  73. # Wrapped by kent@sparky on Thu Sep 10 10:21:20 1992
  74. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  75. echo If this archive is complete, you will see the following message:
  76. echo '          "shar: End of archive 1 (of 5)."'
  77. if test ! -d '1992' ; then
  78.     echo shar: Creating directory \"'1992'\"
  79.     mkdir '1992'
  80. fi
  81. if test -f '1992/buzzard.2.design' -a "${1}" != "-c" ; then 
  82.   echo shar: Will not clobber existing file \"'1992/buzzard.2.design'\"
  83. else
  84.   echo shar: Extracting \"'1992/buzzard.2.design'\" \(25773 characters\)
  85.   sed "s/^X//" >'1992/buzzard.2.design' <<'END_OF_FILE'
  86. X            FIRST & THIRD
  87. X            almost FORTH
  88. X
  89. X    FORTH is a language mostly familiar to users of "small" machines.
  90. XFORTH programs are small because they are interpreted--a function
  91. Xcall in FORTH takes two bytes.  FORTH is an extendable language--
  92. Xbuilt-in primitives are indistinguishable from user-defined
  93. X_words_.  FORTH interpreters are small because much of the system
  94. Xcan be coded in FORTH--only a small number of primitives need to
  95. Xbe implemented.  Some FORTH interpreters can also compile defined
  96. Xwords into machine code, resulting in a fast system.
  97. X
  98. X    FIRST is an incredibly small language which is sufficient for
  99. Xdefining the language THIRD, which is mostly like FORTH.  There are
  100. Xsome differences, and THIRD is probably just enough like FORTH for
  101. Xthose differences to be disturbing to regular FORTH users.
  102. X
  103. X    The only existing FIRST interpreter is written in obfuscated C,
  104. Xand rings in at under 800 bytes of source code, although through
  105. Xdeletion of whitespace and unobfuscation it can be brought to about
  106. X650 bytes.
  107. X
  108. X    This document FIRST defines the FIRST environment and primitives,
  109. Xwith relevent design decision explanations.  It secondly documents
  110. Xthe general strategies we will use to implement THIRD.  The THIRD
  111. Xsection demonstrates how the complete THIRD system is built up
  112. Xusing FIRST.
  113. X
  114. X
  115. XSection 1:  FIRST
  116. X
  117. X
  118. XEnvironment
  119. X
  120. X    FIRST implements a virtual machine.  The machine has three chunks
  121. Xof memory: "main memory", "the stack", and "string storage".  When
  122. Xthe virtual machine wishes to do random memory accesses, they come
  123. Xout of main memory--it cannot access the stack or string storage.
  124. X
  125. X    The stack is simply a standard LIFO data structure that is used
  126. Ximplicitly by most of the FIRST primitives.  The stack is made up
  127. Xof ints, whatever size they are on the host machine.
  128. X
  129. X    String storage is used to store the names of built-in and defined
  130. Xprimitives.  Separate storage is used for these because it allows
  131. Xthe C code to use C string operations, reducing C source code size.
  132. X
  133. X    Main memory is a large array of ints.  When we speak of
  134. Xaddresses, we actually mean indices into main memory.  Main memory
  135. Xis used for two things, primarily: the return stack and the dictionary.
  136. X
  137. X    The return stack is a LIFO data structure, independent of
  138. Xthe abovementioned "the stack", which is used by FIRST to keep
  139. Xtrack of function call return addresses.
  140. X
  141. X    The dictionary is a list of words.  Each word contains a header
  142. Xand a data field.  In the header is the address of the previous word,
  143. Xan index into the string storage indicating where the name of this
  144. Xword is stored, and a "code pointer".  The code pointer is simply
  145. Xan integer which names which "machine-language-primitive" implements
  146. Xthis instruction.  For example, for defined words the code pointer
  147. Xnames the "run some code" primitive, which pushes the current program
  148. Xcounter onto the return stack and sets the counter to the address of
  149. Xthe data field for this word.
  150. X
  151. X    There are several important pointers into main memory.  There is
  152. Xa pointer to the most recently defined word, which is used to start
  153. Xsearches back through memory when compiling words.  There is a pointer
  154. Xto the top of the return stack.  There is a pointer to the current
  155. Xend of the dictionary, used while compiling.
  156. X
  157. X    For the last two pointers, namely the return stack pointer and
  158. Xthe dictionary pointer, there is an important distinction: the pointers
  159. Xthemselves are stored in main memory (in FIRST's main memory).  This
  160. Xis critical, because it means FIRST programs can get at them without
  161. Xany further primitives needing to be defined.
  162. X
  163. X
  164. XInstructions
  165. X
  166. X    There are two kinds of FIRST instructions, normal instructions and
  167. Ximmediate instructions.  Immediate instructions do something significant
  168. Xwhen they are used.  Normal instructions compile a pointer to their
  169. Xexecutable part onto the end of the dictionary.  As we will see, this
  170. Xmeans that by default FIRST simply compiles things.
  171. X
  172. X  Integer Operations
  173. XSymbol    Name        Function
  174. X  -    binary minus    pop top 2 elements of stack, subtract, push
  175. X  *    multiply    pop top 2 elements of stack, multiply, push
  176. X  /    divide        pop top 2 elements of stack, divide, push
  177. X  <0    less than 0    pop top element of stack, push 1 if < 0 else 0
  178. X
  179. XNote that we can synthesize addition and negation from binary minus,
  180. Xbut we cannot synthesize a time efficient divide or multiply from it.
  181. X<0 is synthesizable, but only nonportably.
  182. X
  183. X  Memory Operations
  184. XSymbol    Name        Function
  185. X  @    fetch        pop top of stack, treat as address to push contents of
  186. X  !    store        top of stack is address, 2nd is value; store to memory
  187. X                and pop both off the stack
  188. X
  189. X  Input/Output Operations
  190. XName            Function
  191. Xecho            output top of stack through C's putchar()
  192. Xkey            push C's getchar() onto top of stack
  193. X_read            read a space-delimited word, find it in the
  194. X                dictionary, and compile a pointer to
  195. X                that word's code pointer onto the
  196. X                current end of the dictionary
  197. X
  198. XAlthough _read could be synthesized from key, we need _read to be able
  199. Xto compile words to be able to start any syntheses.
  200. X
  201. X  Execution Operations
  202. XName            Function
  203. Xexit            leave the current function: pop the return stack
  204. X                into the program counter
  205. X
  206. X  Immediate (compilation) Operations
  207. XSymbol    Name        Function
  208. X  :    define        read in the next space-delimited word, add it to
  209. X                the end of our string storage, and generate
  210. X                a header for the new word so that when it
  211. X                is typed it compiles a pointer to itself
  212. X                so that it can be executed.
  213. Ximmediate immediate    when used immediately after a name following a ':',
  214. X                makes the word being defined run whenever
  215. X                it is typed.
  216. X
  217. X: cannot be synthesized, because we could not synthesize anything.
  218. Ximmediate has to be an immediate operation, so it could not be
  219. Xsynthesized unless by default operations were immediate; but that
  220. Xwould preclude our being able to do any useful compilation.
  221. X
  222. X  Stack Operations
  223. XName            Function
  224. Xpick            pop top of stack, use as index into stack and copy up
  225. X                that element
  226. X
  227. XIf the data stack were stored in main memory, we could synthesize pick;
  228. Xbut putting the stack and stack pointer in main memory would significantly
  229. Xincrease the C source code size.
  230. X
  231. X    There are three more primitives, but they are "internal only"--
  232. Xthey have no names and no dictionary entries.  The first is
  233. X"pushint".  It takes the next integer out of the instruction stream
  234. Xand pushes it on the stack.  This could be synthesized, but probably
  235. Xnot without using integer constants.  It is generated by _read when
  236. Xthe input is not a known word.  The second is "compile me".  When
  237. Xthis instruction is executed, a pointer to the word's data field is
  238. Xappended to the dictionary.  The third is "run me"--the word's data
  239. Xfield is taken to be a stream of pointers to words, and is executed.
  240. X
  241. X    One last note about the environment: FIRST builds a very small
  242. Xword internally that it executes as its main loop.  This word calls
  243. X_read and then calls itself.  Each time it calls itself, it uses
  244. Xup a word on the return stack, so it will eventually trash things.
  245. XThis is discussed some more in section 2.
  246. X
  247. X
  248. XHere's a handy summary of all the FIRST words:
  249. X
  250. X    - * /        binary integer operations on the stack
  251. X    <0        is top of stack less than 0?
  252. X    @ !        read from or write to memory
  253. X    echo key    output or input one character
  254. X    _read        read a word from input and compile a pointer to it
  255. X    exit        stop running the current function
  256. X    :        compile the header of a definition
  257. X    immediate    modify the header to create an immediate word
  258. X
  259. X    Here is a sample FIRST program.  I'm assuming you're using
  260. Xthe ASCII character set.  FIRST does not depend upon ASCII, but
  261. Xsince FIRST has no syntax for character constants, one normally has
  262. Xto use decimal values.  This can be gotten around using getchar, though.
  263. XOh.  One other odd thing.  FIRST initially builds its symbol table
  264. Xby calling : several times, so it needs to get the names of the base
  265. Xsymbols as its first 13 words of input.  You could even name them
  266. Xdifferently if you wanted.
  267. X    These FIRST programs have FORTH comments in them: they are contained
  268. Xinside parentheses.  FIRST programs cannot have FORTH comments; but I need
  269. Xsome device to indicate what's going on.  (THIRD programs are an entirely
  270. Xdifferent subject.)
  271. X
  272. X    ( Our first line gives the symbols for the built-ins )
  273. X: immediate _read @ ! - * / <0 exit echo key _pick
  274. X
  275. X    ( now we define a simple word that will print out a couple characters )
  276. X
  277. X: L            ( define a word named 'L' )
  278. X  108 echo        ( output an ascii 'l' )
  279. X  exit
  280. X
  281. X: hello            ( define a word named 'hello')
  282. X  72 echo        ( output an ascii 'H' )
  283. X  101 echo        ( output an ascii 'e' )
  284. X  111            ( push ascii 'o' onto the stack )
  285. X  L L            ( output two ascii 'l's )
  286. X  echo            ( output the 'o' we pushed on the stack before )
  287. X  10 echo        ( print a newline )
  288. X  exit            ( stop running this routine )
  289. X
  290. X: test immediate    ( define a word named 'test' that runs whenever typed )
  291. X  hello            ( call hello )
  292. X  exit
  293. X
  294. Xtest
  295. X
  296. X( The result of running this program should be: 
  297. XHello
  298. X)
  299. X
  300. X
  301. XSection 2: Motivating THIRD
  302. X
  303. X    What is missing from FIRST?  There are a large number of
  304. Ximportant primitives that aren't implemented, but which are
  305. Xeasy to implement.  drop , which throws away the top of the
  306. Xstack, can be implemented as { 0 * + } -- that is, multiply
  307. Xthe top of the stack by 0 (which turns the top of the stack
  308. Xinto a 0), and then add the top two elements of the stack.
  309. X
  310. X    dup , which copies the top of the stack, can be easily
  311. Ximplemented using temporary storage locations.  Conveniently,
  312. XFIRST leaves memory locations 3, 4, and 5 unused.  So we can
  313. Ximplement dup by writing the top of stack into 3, and then
  314. Xreading it out twice: { 3 ! 3 @ 3 @ }.
  315. X
  316. X    we will never use the FIRST primitive 'pick' in building THIRD,
  317. Xjust to show that it can be done; 'pick' is only provided because
  318. Xpick itself cannot be built out of the rest of FIRST's building
  319. Xblocks.
  320. X
  321. X    So, instead of worrying about stack primitives and the
  322. Xlike, what else is missing from FIRST?  We get recursion, but
  323. Xno control flow--no conditional operations.  We cannot at the
  324. Xmoment write a looping routine which terminates.
  325. X
  326. X    Another glaring dissimilarity between FIRST and FORTH is
  327. Xthat there is no "command mode"--you cannot be outside of a
  328. X: definition and issue some straight commands to be executed.
  329. XAlso, as we noted above, we cannot do comments.
  330. X
  331. X    FORTH also provides a system for defining new data types,
  332. Xusing the words [in one version of FORTH] <builds and does> .
  333. XWe would like to implement these words as well.
  334. X
  335. X    As the highest priority thing, we will build control flow
  336. Xstructures first.  Once we have control structures, we can
  337. Xwrite recursive routines that terminate, and we are ready to
  338. Xtackle tasks like parsing, and the building of a command mode.
  339. X
  340. X    By the way, location 0 holds the dictionary pointer, location
  341. X1 holds the return stack pointer, and location 2 should always
  342. Xbe 0--it's a fake dictionary entry that means "pushint".
  343. X
  344. X
  345. XSection 3: Building THIRD
  346. X
  347. X        In this section, I'm going to keep my conversation
  348. X        indented to this depth, rather than using fake comments--
  349. X        because we'll have real comments eventually.
  350. X
  351. X        The first thing we have to do is give the symbols for our
  352. X        built-ins.
  353. X
  354. X: immediate _read @ ! - * / < exit echo key _pick
  355. X
  356. X        Next we want to be mildly self commenting, so we define
  357. X        the word 'r' to push the *address of the return stack
  358. X        pointer* onto the stack--NOT the value of the return 
  359. X        stack pointer.  (In fact, when we run r, the value of
  360. X        the return stack pointer is temporarily changed.)
  361. X
  362. X: r 1 exit
  363. X
  364. X        Next, we're currently executing a short loop that contains
  365. X        _read and recursion, which is slowly blowing up the return
  366. X        stack.  So let's define a new word, from which you can
  367. X        never return.  What it does is drops the top value off
  368. X        the return stack, calls _read, then calls itself.  Because
  369. X        it kills the top of the return stack, it can recurse
  370. X        indefinitely.
  371. X
  372. X: ]
  373. X  r @            Get the value of the return stack pointer
  374. X  1 -            Subtract one
  375. X  r !            Store it back into the return stack pointer
  376. X  _read            Read and compile one word
  377. X  ]            Start over
  378. X
  379. X        Notice that we don't need to exit, since we never come
  380. X        back.  Also, it's possible that an immediate word may
  381. X        get run during _read, and that _read will never return!
  382. X
  383. X        Now let's get compile running.
  384. X
  385. X: main immediate ]
  386. Xmain
  387. X
  388. X        Next off, I'm going to do this the easy but non-portable
  389. X        way, and put some character constant definitions in.
  390. X        I wanted them at the top of the file, but that would have
  391. X        burned too much of the return stack.
  392. X
  393. X: '"'    34    exit
  394. X: ')'    41    exit
  395. X: '\n'    10    exit
  396. X: 'space' 32    exit
  397. X: '0'    48    exit
  398. X: '-'    45    exit
  399. X
  400. X: cr '\n' echo exit
  401. X
  402. X        Next, we want to define some temporary variables for
  403. X        locations 3, 4, and 5, since this'll make our code look
  404. X        clearer.
  405. X: _x 3 @ exit
  406. X: _x! 3 ! exit
  407. X: _y 4 @ exit
  408. X: _y! 4 ! exit
  409. X
  410. X        Ok.  Now, we want to make THIRD look vaguely like FORTH,
  411. X        so we're going to define ';'.  What ; ought to do is
  412. X        terminate a compilation, and turn control over to the
  413. X        command-mode handler.  We don't have one, so all we want
  414. X        ';' to do for now is compile 'exit' at the end of the
  415. X        current word.  To do this we'll need several other words.
  416. X        
  417. X        Swap by writing out the top two elements into temps, and
  418. X        then reading them back in the other order.
  419. X: swap _x! _y! _x _y exit
  420. X        Take another look and make sure you see why that works,
  421. X        since it LOOKS like I'm reading them back in the same
  422. X        order--in fact, it not only looks like it, but I AM!
  423. X
  424. X        Addition might be nice to have.  To add, we need to
  425. X        negate the top element of the stack, and then subtract.
  426. X        To negate, we subtract from 0.
  427. X: +
  428. X  0 swap -
  429. X  -
  430. X  exit
  431. X
  432. X        Create a copy of the top of stack
  433. X: dup _x! _x _x exit
  434. X
  435. X        Get a mnemonic name for our dictionary pointer--we need
  436. X        to compile stuff, so it goes through this.
  437. X: h 0 exit
  438. X
  439. X        We're going to need to advance that pointer, so let's
  440. X        make a generic pointer-advancing function.
  441. X        Given a pointer to a memory location, increment the value
  442. X        at that memory location.
  443. X: inc
  444. X  dup @            Get another copy of the address, and get the value
  445. X            so now we have value, address on top of stack.
  446. X  1 +            Add one to the value
  447. X  swap            Swap to put the address on top of the stack
  448. X  ! exit        Write it to memory
  449. X
  450. X        , is a standard FORTH word.  It should write the top of 
  451. X        stack into the dictionary, and advance the pointer
  452. X: ,
  453. X  h @            Get the value of the dictionary pointer
  454. X  !            Write the top of stack there
  455. X  h inc            And increment the dictionary pointer
  456. X  exit
  457. X
  458. X        ' is a standard FORTH word.  It should push the address
  459. X        of the word that follows it onto the stack.  We could
  460. X        do this by making ' immediate, but then it'd need to
  461. X        parse the next word.  Instead, we compile the next word
  462. X        as normal.  When ' is executed, the top of the return
  463. X        stack will point into the instruction stream immediately
  464. X        after the ' .  We push the word there, and advance the
  465. X        return stack pointer so that we don't execute it.
  466. X: '
  467. X  r @            Get the address of the top of return stack
  468. X            We currently have a pointer to the top of return stack
  469. X  @            Get the value from there
  470. X            We currently have a pointer to the instruction stream
  471. X  dup            Get another copy of it--the bottom copy will stick
  472. X                around until the end of this word
  473. X  1 +            Increment the pointer, pointing to the NEXT instruction
  474. X  r @ !            Write it back onto the top of the return stack
  475. X            We currently have our first copy of the old pointer
  476. X                to the instruction stream
  477. X  @            Get the value there--the address of the "next word"
  478. X  exit
  479. X
  480. X        Now we're set.  ; should be an immediate word that pushes
  481. X        the address of exit onto the stack, then writes it out.
  482. X: ; immediate
  483. X  ' exit         Get the address of exit
  484. X  ,            Compile it
  485. X  exit            And we should return
  486. X
  487. X        Now let's test out ; by defining a useful word:
  488. X: drop 0 * + ;
  489. X
  490. X        Since we have 'inc', we ought to make 'dec':
  491. X: dec dup @ 1 - swap ! ;
  492. X
  493. X        Our next goal, now that we have ;, is to implement
  494. X        if-then.  To do this, we'll need to play fast and
  495. X        loose with the return stack, so let's make some
  496. X        words to save us some effort.
  497. X
  498. X        First we want a word that pops off the top of the normal
  499. X        stack and pushes it on top of the return stack.  We'll
  500. X        call this 'tor', for TO-Return-stack.   It sounds easy,
  501. X        but when tor is running, there's an extra value on the
  502. X        return stack--tor's return address!  So we have to pop
  503. X        that off first...  We better just bite the bullet and
  504. X        code it out--but we can't really break it into smaller
  505. X        words, because that'll trash the return stack.
  506. X: tor
  507. X  r @ @            Get the value off the top of the return stack
  508. X  swap            Bring the value to be pushed to the top of stack
  509. X  r @ !            Write it over the current top of return stack
  510. X  r @ 1 + r !        Increment the return stack pointer--but can't use inc
  511. X  r @ !            Store our return address back on the return stack
  512. X;
  513. X
  514. X        Next we want the opposite routine, which pops the top
  515. X        of the return stack, and puts it on the normal stack.
  516. X: fromr
  517. X  r @ @            Save old value
  518. X  r @ 1 - r !        Decrement pointer
  519. X  r @ @            Get value that we want off
  520. X  swap            Bring return address to top
  521. X  r @ !            Store it and return
  522. X;
  523. X
  524. X        Now, if we have a routine that's recursing, and we
  525. X        want to be polite about the return stack, right before
  526. X        we recurse we can run { fromr drop } so the stack won't
  527. X        blow up.  This means, though, that the first time we
  528. X        enter this recursive routine, we blow our *real* return
  529. X        address--so when we're done, we'll return up two levels.
  530. X        To save a little, we make 'tail' mean { fromr drop };
  531. X        however, it's more complex since there's a new value on
  532. X        top of the return stack.
  533. X: tail fromr fromr drop tor ;
  534. X
  535. X        Now, we want to do 'if'.  To do this, we need to convert
  536. X        values to boolean values.  The next few words set this
  537. X        up.    
  538. X
  539. X        minus gives us unary negation.
  540. X: minus 0 swap - ;
  541. X
  542. X        If top of stack is boolean, bnot gives us inverse
  543. X: bnot 1 swap - ;
  544. X
  545. X        To compare two numbers, subtract and compare to 0.
  546. X: < - <0 ;
  547. X
  548. X        logical turns the top of stack into either 0 or 1.
  549. X: logical
  550. X  dup            Get two copies of it
  551. X  0 <            1 if < 0, 0 otherwise
  552. X  swap minus        Swap number back up, and take negative
  553. X  0 <            1 if original was > 0, 0 otherwise
  554. X  +            Add them up--has to be 0 or 1!
  555. X;
  556. X
  557. X        not returns 1 if top of stack is 0, and 0 otherwise
  558. X: not logical bnot ;
  559. X
  560. X        We can test equality by subtracting and comparing to 0.
  561. X: = - not ;
  562. X
  563. X        Just to show how you compute a branch:  Suppose you've
  564. X        compiled a call to branch, and immediately after it is
  565. X        an integer constant with the offset of how far to branch.
  566. X        To branch, we use the return stack to read the offset, and
  567. X        add that on to the top of the return stack, and return.
  568. X: branch
  569. X  r @            Address of top of return stack
  570. X  @            Our return address
  571. X  @            Value from there: the branch offset
  572. X  r @ @            Our return address again
  573. X  +            The address we want to execute at
  574. X  r @ !            Store it back onto the return stack
  575. X;
  576. X
  577. X        For conditional branches, we want to branch by a certain
  578. X        amount if true, otherwise we want to skip over the branch
  579. X        offset constant--that is, branch by one.  Assuming that
  580. X        the top of the stack is the branch offset, and the second
  581. X        on the stack is 1 if we should branch, and 0 if not, the
  582. X        following computes the correct branch offset.
  583. X: computebranch 1 - * 1 + ;
  584. X
  585. X        Branch if the value on top of the stack is 0.
  586. X: notbranch
  587. X  not
  588. X  r @ @ @        Get the branch offset
  589. X  computebranch        Adjust as necessary
  590. X  r @ @ +        Calculate the new address
  591. X  r @ !            Store it
  592. X;
  593. X
  594. X        here is a standard FORTH word which returns a pointer to
  595. X        the current dictionary address--that is, the value of
  596. X        the dictionary pointer.
  597. X: here h @ ;
  598. X
  599. X        We're ALL SET to compile if...else...then constructs!
  600. X        Here's what we do.  When we get 'if', we compile a call
  601. X        to notbranch, and then compile a dummy offset, because
  602. X        we don't know where the 'then' will be.  On the *stack*
  603. X        we leave the address where we compiled the dummy offset.
  604. X        'then' will calculate the offset and fill it in for us.
  605. X: if immediate
  606. X  ' notbranch ,        Compile notbranch
  607. X  here            Save the current dictionary address
  608. X  0 ,            Compile a dummy value
  609. X;
  610. X
  611. X        then expects the address to fixup to be on the stack.
  612. X: then immediate
  613. X  dup            Make another copy of the address
  614. X  here            Find the current location, where to branch to
  615. X  swap -        Calculate the difference between them
  616. X  swap !        Bring the address to the top, and store it.
  617. X;
  618. X
  619. X        Now that we can do if...then statements, we can do
  620. X        some parsing!  Let's introduce real FORTH comments.
  621. X        find-) will scan the input until it finds a ), and
  622. X        exit.
  623. X: find-)
  624. X  key            Read in a character
  625. X  ')' =            Compare it to close parentheses
  626. X  not if        If it's not equal
  627. X    tail find-)        repeat (popping R stack)
  628. X  then            Otherwise branch here and exit
  629. X;
  630. X
  631. X: ( immediate
  632. X  find-)
  633. X;
  634. X
  635. X( we should be able to do FORTH-style comments now )
  636. X
  637. X( now that we've got comments, we can comment the rest of the code
  638. X  in a legitimate [self parsing] fashion.  Note that you can't
  639. X  nest parentheses... )
  640. X
  641. X: else immediate
  642. X  ' branch ,        ( compile a definite branch )
  643. X  here            ( push the backpatching address )
  644. X  0 ,            ( compile a dummy offset for branch )
  645. X  swap            ( bring old backpatch address to top )
  646. X  dup here swap -    ( calculate the offset from old address )
  647. X  swap !        ( put the address on top and store it )
  648. X;
  649. X
  650. X: over _x! _y! _y _x _y ;
  651. X
  652. X: add
  653. X  _x!            ( save the pointer in a temp variable )
  654. X  _x @            ( get the value pointed to )
  655. X  +            ( add the incremement from on top of the stack )
  656. X  _x !            ( and save it )
  657. X;
  658. X
  659. X: allot    h add ;
  660. X
  661. X: maybebranch
  662. X  logical        ( force the TOS to be 0 or 1 )
  663. X  r @ @ @        ( load the branch offset )
  664. X  computebranch        ( calculate the condition offset [either TOS or 1])
  665. X  r @ @ +        ( add it to the return address )
  666. X  r @ !            ( store it to our return address and return )
  667. X;
  668. X
  669. X: mod _x! _y!        ( get x then y off of stack )
  670. X  _y _y _x / _x *    ( y - y / x * x )
  671. X  -
  672. X;
  673. X
  674. X: printnum
  675. X  dup
  676. X  10 mod '0' +
  677. X  swap 10 / dup
  678. X  if
  679. X    printnum
  680. X    echo
  681. X  else
  682. X    drop
  683. X    echo
  684. X  then
  685. X;
  686. X
  687. X: .
  688. X  dup 0 <
  689. X  if
  690. X    '-' echo minus
  691. X  then
  692. X  printnum
  693. X  'space' echo
  694. X;
  695. X
  696. X: debugprint dup . cr ;
  697. X
  698. X( the following routine takes a pointer to a string, and prints it,
  699. X  except for the trailing quote.  returns a pointer to the next word
  700. X  after the trailing quote )
  701. X
  702. X: _print
  703. X  dup 1 +
  704. X  swap @
  705. X  dup '"' =
  706. X  if
  707. X    drop exit
  708. X  then
  709. X  echo
  710. X  tail _print
  711. X;
  712. X
  713. X: print _print ;
  714. X
  715. X  ( print the next thing from the instruction stream )
  716. X: immprint
  717. X  r @ @
  718. X  print
  719. X  r @ !
  720. X;
  721. X
  722. X: find-"
  723. X  key dup ,
  724. X  '"' =
  725. X  if
  726. X    exit
  727. X  then
  728. X  tail find-"
  729. X;
  730. X
  731. X: " immediate
  732. X  key drop
  733. X  ' immprint ,
  734. X  find-"
  735. X;
  736. X
  737. X: do immediate
  738. X  ' swap ,        ( compile 'swap' to swap the limit and start )
  739. X  ' tor ,        ( compile to push the limit onto the return stack )
  740. X  ' tor ,        ( compile to push the start on the return stack )
  741. X  here            ( save this address so we can branch back to it )
  742. X;
  743. X
  744. X: i r @ 1 - @ ;
  745. X: j r @ 3 - @ ;
  746. X
  747. X: > swap < ;
  748. X: <= 1 + < ;
  749. X: >= swap <= ;
  750. X
  751. X: inci 
  752. X  r @ 1 -     ( get the pointer to i )
  753. X  inc        ( add one to it )
  754. X  r @ 1 - @     ( find the value again )
  755. X  r @ 2 - @    ( find the limit value )
  756. X  <=
  757. X  if
  758. X    r @ @ @ r @ @ + r @ ! exit        ( branch )
  759. X  then
  760. X  fromr 1 +
  761. X  fromr drop
  762. X  fromr drop
  763. X  tor
  764. X;
  765. X
  766. X: loop immediate ' inci @ here - , ;
  767. X
  768. X: loopexit
  769. X
  770. X  fromr drop        ( pop off our return address )
  771. X  fromr drop        ( pop off i )
  772. X  fromr drop        ( pop off the limit of i )
  773. X;            ( and return to the caller's caller routine )
  774. X
  775. X: execute
  776. X  8 !
  777. X  ' exit 9 !
  778. X  8 tor
  779. X;
  780. X
  781. X: :: ;          ( :: is going to be a word that does ':' at runtime )
  782. X
  783. X: fix-:: immediate 3 ' :: ! ;
  784. Xfix-::
  785. X
  786. X        ( Override old definition of ':' with a new one that invokes ] )
  787. X: : immediate :: ] ;
  788. X
  789. X: command
  790. X  here 5 !              ( store dict pointer in temp variable )
  791. X  _read                 ( compile a word )
  792. X                        ( if we get control back: )
  793. X  here 5 @
  794. X  = if
  795. X    tail command        ( we didn't compile anything )
  796. X  then
  797. X  here 1 - h !          ( decrement the dictionary pointer )
  798. X  here 5 @              ( get the original value )
  799. X  = if
  800. X    here @              ( get the word that was compiled )
  801. X    execute             ( and run it )
  802. X  else
  803. X    here @              ( else it was an integer constant, so push it )
  804. X    here 1 - h !        ( and decrement the dictionary pointer again )
  805. X  then
  806. X  tail command
  807. X;
  808. X
  809. X: make-immediate        ( make a word just compiled immediate )
  810. X  here 1 -              ( back up a word in the dictionary )
  811. X  dup dup               ( save the pointer to here )
  812. X  h !                   ( store as the current dictionary pointer )
  813. X  @                     ( get the run-time code pointer )
  814. X  swap                  ( get the dict pointer again )
  815. X  1 -                   ( point to the compile-time code pointer )
  816. X  !                     ( write run-time code pointer on compile-time pointer )
  817. X;
  818. X
  819. X: <build immediate
  820. X  make-immediate        ( make the word compiled so far immediate )
  821. X  ' :: ,                ( compile '::', so we read next word )
  822. X  2 ,                   ( compile 'pushint' )
  823. X  here 0 ,              ( write out a 0 but save address for does> )
  824. X  ' , ,                 ( compile a push that address onto dictionary )
  825. X;
  826. X
  827. X: does> immediate
  828. X  ' command ,           ( jump back into command mode at runtime )
  829. X  here swap !           ( backpatch the build> to point to here )
  830. X  2 ,                   ( compile run-code primitive so we look like a word )
  831. X  ' fromr ,             ( compile fromr, which leaves var address on stack )
  832. X;
  833. X
  834. X
  835. X: _dump                 ( dump out the definition of a word, sort of )
  836. X  dup " (" . " , "
  837. X  dup @                 ( save the pointer and get the contents )
  838. X  dup ' exit
  839. X  = if
  840. X        " ;)" cr exit
  841. X  then
  842. X  . " ), "
  843. X  1 +
  844. X  tail _dump
  845. X;
  846. X
  847. X: dump _dump ;
  848. X
  849. X: # . cr ;
  850. X  
  851. X: var <build , does> ;
  852. X: constant <build , does> @ ;
  853. X: array <build allot does> + ;
  854. X
  855. X: [ immediate command ;
  856. X: _welcome " Welcome to THIRD.
  857. XOk.
  858. X" ;
  859. X
  860. X: ; immediate ' exit , command exit
  861. X
  862. X[
  863. X
  864. X_welcome
  865. X
  866. END_OF_FILE
  867.   if test 25773 -ne `wc -c <'1992/buzzard.2.design'`; then
  868.     echo shar: \"'1992/buzzard.2.design'\" unpacked with wrong size!
  869.   fi
  870.   # end of '1992/buzzard.2.design'
  871. fi
  872. if test -f '1992/gson.c' -a "${1}" != "-c" ; then 
  873.   echo shar: Will not clobber existing file \"'1992/gson.c'\"
  874. else
  875.   echo shar: Extracting \"'1992/gson.c'\" \(1513 characters\)
  876.   sed "s/^X//" >'1992/gson.c' <<'END_OF_FILE'
  877. X#include <stdio.h> 
  878. X
  879. Xlong a
  880. X[4],b[
  881. X4],c[4]
  882. X,d[0400],e=1;
  883. Xtypedef struct f{long g
  884. X,h,i[4]       ,j;struct f*k;}f;f g,*
  885. Xl[4096             ]; char h[256],*m,k=3;
  886. X             long n    (o, p,q)long*o,*p,*q;{
  887. X             long r          =4,s,i=0;for(;r--;s=i^
  888. X             *o^*p,                i=i&*p|(i|*p)&~*o++,*q
  889. X             ++=s,p                ++);return i;}t(i,p)long*p
  890. X             ;{*c=d          [i],n(a,c,b),n(p,b,p);}u(j)f*j;{j->h
  891. X             =(j->g    =j->i[0]|j->i[1]|j->i[2]|j->i[3])&4095;}v(
  892. Xj,s)f*             j; {int i; for(j->k->k&&v(j->k, ' '),fseek(
  893. Xstdin,       j->j, 0);i=getchar(),putchar(i-'\n'?i:s),i-
  894. X'\n';);}w(o,r,j,x,p)f*o,*j;long p;{f q;int 
  895. Xs,i=o->h;q.k=o;r>i?j=l[r=i]:r<i&&
  896. X(s=r&~i)?(s|=s>>1, s|=s
  897. X>>2,s|=s>>4,s
  898. X|=s>>8
  899. X,j=l[r
  900. X=((r&i
  901. X             |s)&~(s>>1))-1&i]):0;--x;for
  902. X         (;x&&!(p&i);p>>=1);for(;!x&&j;n(o->i,j->i,q.
  903. X        i),u(&q),q.g||(q.j=j->j,v(&q,'\n')),j=j->k);for(;x;j=x
  904. X     ?j->k:0){for(;!j&&((r=(r&i)-1&i)-i&&(r&p)?2:(x=0));j=l[r]);!
  905. X      x||(j->g&~o->g)||n                  (o->i,j->i,q.i)||(
  906. X    u(&q), q.j=j                          ->j,q.g?w(&q
  907. X   ,r,j->k,x                              ,p):v(&q,
  908. X  '\n'));                                 }}y(){f
  909. X j;char                                       *z,*p;
  910. Xfor(;m                                    ? j.j=
  911. Xftell(                                    stdin)
  912. X,7,(m=                 gets(m                    ))||w(
  913. X&g,315                 *13,l[                    4095]
  914. X ,k,64*                 64)&0:                       0;n(g
  915. X  .i,j.i,             b)||(u                    (&j),j.
  916. X   k=l[j.h],l[j.h]= &j,y())){for(z=                p=h;*z&&(
  917. X    d[*z++]||(p=0)););for(z=p?n(j.i              ,j.i,j.i)+h:"";
  918. X  *z;t(*z++,j.i));}}main(o,p)char**         p; {for(;m = *++p;)for(;*m-
  919. X'-'?*m:(k= -atoi(m))&0;d[*m]||(d[*m         ]=e,e<<=1),t(*m++,g.i)); u(&
  920. X                 g),m=h
  921. X                 ,y();}
  922. END_OF_FILE
  923.   if test 1513 -ne `wc -c <'1992/gson.c'`; then
  924.     echo shar: \"'1992/gson.c'\" unpacked with wrong size!
  925.   fi
  926.   # end of '1992/gson.c'
  927. fi
  928. if test -f '1992/guidelines' -a "${1}" != "-c" ; then 
  929.   echo shar: Will not clobber existing file \"'1992/guidelines'\"
  930. else
  931.   echo shar: Extracting \"'1992/guidelines'\" \(22215 characters\)
  932.   sed "s/^X//" >'1992/guidelines' <<'END_OF_FILE'
  933. X9th International Obfuscated C Code Contest Guidelines, Hints and Comments
  934. X
  935. X
  936. XABOUT THIS FILE:
  937. X
  938. X    This file is intended to help people who wish to submit entries to
  939. X    the International Obfuscated C Code Contest (IOCCC for short).
  940. X
  941. X    This is not the IOCCC rules, though it does contain comments about
  942. X    them.  The guidelines should be viewed as hints and suggestions.
  943. X    Entries that violate the guidelines but remain within the rules are
  944. X    allowed.  Even so, you are safer if you remain within the guidelines.
  945. X
  946. X    You should read the current IOCCC rules, prior to submitting entries.
  947. X    The rules are typically sent out with these guidelines.
  948. X
  949. X
  950. XWHAT IS NEW IN 1992:
  951. X
  952. X    The size rules are different this year.  There is a more relaxed
  953. X    rule to encourage formatting styles beyond rectangular blobs of C
  954. X    code.  The build file (how to compile) has been expanded as well.
  955. X    See the rules, and OUR LIKES AND DISLIKES for details.
  956. X
  957. X    The entry format is better (for us anyway).  The program mkentry.c
  958. X    provides a convenient way to form an entry.  See ENTRY FORMAT.
  959. X
  960. X    The original entry source, build and resulting binary should be
  961. X    treated as read-only.  There is a provision to allow entries to
  962. X    modify these files indirectly.  See ENTRY FORMAT.
  963. X
  964. X    This year, we are experimenting with a new category of programs:
  965. X    X clients.  X client entries should be as portable as possible.
  966. X    See OUR LIKES AND DISLIKES.
  967. X
  968. X
  969. XHINTS AND SUGGESTIONS:
  970. X
  971. X    You are encouraged to examine the winners of previous contests.  See
  972. X    FOR MORE INFORMATION for details on how to get previous winners.
  973. X
  974. X    Keep in mind that rules change from year to year, so some winning entries
  975. X    may not be valid entries this year.  What was unique and novel one year
  976. X    might be 'old' the next year.
  977. X
  978. X    An entry is usually examined in a number of ways.  We typically apply
  979. X    a number of tests to an entry:
  980. X
  981. X    * look at the original source
  982. X    * If it is ANSI, convert tri-graphs to ASCII
  983. X    * C pre-process the source ignoring '#include' lines
  984. X    * C pre-process the source ignoring '#define' and '#include' lines
  985. X    * run it through a C beautifier
  986. X    * examine the algorithm
  987. X    * lint it
  988. X    * compile it
  989. X    * execute it
  990. X
  991. X    You should consider how your entry looks in each of the above tests.
  992. X    You should ask yourself if your entry remains obscure after it has been
  993. X    'cleaned up' by the C pre-processor and a C beautifier.
  994. X
  995. X    Your entry need not do well under all, or in most tests.  In certain
  996. X    cases, a test is not important.  Entries that compete for the
  997. X    'strangest/most creative source layout' need not do as well as
  998. X    others in terms of their algorithm.  On the other hand, given
  999. X    two such entries, we are more inclined to pick the entry that
  1000. X    does something interesting when you run it.
  1001. X
  1002. X    We try to avoid limiting creativity in our rules.  As such, we leave
  1003. X    the contest open for creative rule interpretation.  As in real life
  1004. X    programming, interpreting a requirements document or a customer request
  1005. X    is important.  For this reason, we often award 'worst abuse of the
  1006. X    rules' to an entry that illustrates this point in an ironic way.
  1007. X
  1008. X    If you do plan to abuse the rules, we suggest that you let us know
  1009. X    in the remarks section.  Please note that an invitation to abuse
  1010. X    is not an invitation to break.  We are strict when it comes to the
  1011. X    3217 byte size limit.  Also, abusing the entry format tends to
  1012. X    annoy more than amuse.
  1013. X
  1014. X    We do realize that there are holes in the rules, and invite entries
  1015. X    to attempt to exploit them.  We will award 'worst abuse of the rules'
  1016. X    and then plug the hole next year.  Even so, we will attempt to use
  1017. X    the smallest plug needed, if not smaller.  :-)
  1018. X
  1019. X    Check out your program and be sure that it works.  We sometimes make
  1020. X    the effort to debug an entry that has a slight problem, particularly
  1021. X    in or near the final round.  On the other hand, we have seen some
  1022. X    of the best entries fall down because they didn't work.
  1023. X
  1024. X    We tend to look down on a prime number printer, that claims that
  1025. X    16 is a prime number.  If you do have a bug, you are better off
  1026. X    documenting it.  Noting "this entry sometimes prints the 4th power
  1027. X    of a prime by mistake" would save the above entry.  And sometimes,
  1028. X    a strange bug/feature can even help the entry!  Of course, a correctly
  1029. X    working entry is best.
  1030. X
  1031. X
  1032. XOUR LIKES AND DISLIKES:
  1033. X
  1034. X    Doing masses of #defines to obscure the source has become 'old'.  We
  1035. X    tend to 'see thru' masses of #defines due to our pre-processor tests
  1036. X    that we apply.  Simply abusing #defines or -Dfoo=bar won't go as far
  1037. X    as a program that is more well rounded in confusion.
  1038. X
  1039. X    Many ANSI C compilers dislike the following code, and so do we:
  1040. X
  1041. X    #define d define
  1042. X    #d foo           <-- don't expect this to turn into #define foo
  1043. X
  1044. X    int i;
  1045. X    j;           <-- don't use such implicit type declarations
  1046. X    int k;
  1047. X
  1048. X    We suggest that you use ANSI C compilers if possible.  If you must
  1049. X    use non-ANSI C, such as K&R C, try to avoid areas that give ANSI C
  1050. X    compilers problems.
  1051. X
  1052. X    Small programs are best when they are short, obscure and concise.
  1053. X    While such programs are not as complex as other winners, they do
  1054. X    serve a useful purpose.  They are often the only program that people
  1055. X    attempt to completely understand.  For this reason, we look for
  1056. X    programs that are compact, and are instructional.
  1057. X
  1058. X    One line programs should be short one line programs, say around 80
  1059. X    bytes long.  Getting close to 160 bytes is a bit too long for one liners
  1060. X    in our books.
  1061. X
  1062. X    We tend to dislike programs that:
  1063. X
  1064. X    * are very hardware specific
  1065. X    * are very OS or Un*x version specific
  1066. X         (index/strchr differences are ok, but socket/streams specific
  1067. X          code is likely not to be)
  1068. X    * dump core or have compiler warnings
  1069. X         (it is ok only if you warn us in the 'remark' header item)
  1070. X    * won't compile under both BSD or SYS V Un*x
  1071. X    * abusing the build file to get around the size limit
  1072. X    * obfuscate by excessive use of ANSI tri-graphs
  1073. X    * are longer than they need to be
  1074. X    * are similar to previous winners
  1075. X    * are identical to previous losers  :-)
  1076. X
  1077. X    Unless you are cramped for space, or unless you are entering the
  1078. X    'best one liner' category, we suggest that you format your program
  1079. X    in a more creative way than simply forming excessively long lines.
  1080. X
  1081. X    The build file should not be used to try and get around the size
  1082. X    limit.  It is one thing to make use of a several -D's to help out,
  1083. X    but it is quite another to use 200+ bytes of -D's in order to
  1084. X    try and squeeze the source under the size limit.  You should feel
  1085. X    free to make use of the build file space, but you are better off
  1086. X    if you show some amount of restraint.
  1087. X
  1088. X    We allowed whitespace, and in certain cases ; { or } do not impact
  1089. X    your program size (up to a certain point), because we want to get
  1090. X    away from source that is simply a compact blob of characters.
  1091. X
  1092. X    Given two versions of the same program, one that is a compact blob
  1093. X    of code, and the other that is formatted more like a typical C
  1094. X    program, we tend to favor the second version.  Of course, a third
  1095. X    version of the same program that is formatted in an interesting
  1096. X    and/or obfuscated way, would definitely win over the first two!
  1097. X
  1098. X    We suggest that you avoid trying for the 'smallest self-replicating'
  1099. X    program.  We are amazed at the many different sizes that claim
  1100. X    to be the smallest.  There is nothing wrong with self-replicating
  1101. X    programs.  In fact, a number of winners have been self-replicating.
  1102. X    You might want to avoid the claim of 'smallest', lest we (or others)
  1103. X    know of a smaller one!
  1104. X
  1105. X    X client entries should be as portable as possible.  Entries that
  1106. X    adapt to a wide collection of environments will be favored.  Don't
  1107. X    depend on a particular type of display.  For example, don't depend
  1108. X    on color or a given size.  Don't require backing store.
  1109. X
  1110. X    X client entries should avoid using X related libraries and
  1111. X    software that is not in wide spread use.  We ask that such X client
  1112. X    entries restrict themselves to only the low level Xlib and the
  1113. X    Athena widget set (libX11.a, libXaw.a, libXmu.a and libXt.a).
  1114. X    Don't use M*tif, Xv*ew, or OpenL*ok toolkits, since not everyone
  1115. X    has them.  Avoid depending on a particular window manager.  Not
  1116. X    everyone has X11r5, and some people are stuck back in X11r3 (or
  1117. X    earlier), so try to target X11r4 without requiring X11r4.  Better
  1118. X    yet, try to make your entry run on all version 11 X Window Systems.
  1119. X
  1120. X    X client entries should not to depend on particular items on
  1121. X    .Xdefaults.  If you must do so, be sure to note the required lines
  1122. X    in the ---remark--- section.  Better yet, give an xrdb -merge
  1123. X    command as part of the build.
  1124. X
  1125. X    We like programs that:
  1126. X
  1127. X    * are as concise and small as they need to be
  1128. X    * do something at least quasi-interesting
  1129. X    * pass lint without complaint (not a requirement, but it is nice)
  1130. X    * are portable
  1131. X    * are unique or novel in their obfuscation style
  1132. X    * MAKE USE OF A NUMBER OF DIFFERENT TYPES OF OBFUSCATION
  1133. X    * make us laugh and/or throw up  :-)
  1134. X
  1135. X    Some types of programs can't excel in some areas.  Of course, your
  1136. X    program doesn't have to excel in all areas, but doing well in several
  1137. X    areas really does help.
  1138. X
  1139. X    We freely admit that interesting, creative or humorous comments in
  1140. X    the ---remark--- section helps your chance of winning.  If you had to
  1141. X    read of many twisted entries, you too would enjoy a good laugh or two.
  1142. X    We think the readers of the contest winners do as well.
  1143. X
  1144. X    Be creative!
  1145. X
  1146. X
  1147. XENTRY FORMAT:
  1148. X
  1149. X    In order to help us process the many entries, we must request your
  1150. X    assistance by formatting your entries in a certain way.  This format,
  1151. X    in addition, allows us to quickly separate information about the
  1152. X    author from the program itself.  (see JUDGING PROCESS)
  1153. X
  1154. X    We have provided the program, mkentry, as an example of how to
  1155. X    format entries.  You should be aware of the following warning that
  1156. X    is found in mkentry.c:
  1157. X
  1158. X    This program attempts to implement the IOCCC rules.  Every
  1159. X    attempt has been made to make sure that this program produces
  1160. X    an entry that conforms to the contest rules.  In all cases,
  1161. X    where this program differs from the contest rules, the
  1162. X    contest rules will be used.  Be sure to check with the
  1163. X    contest rules before submitting an entry.
  1164. X
  1165. X    You are not required to use mkentry.  It is convenient, however,
  1166. X    as it attempts to uuencode the needed files, and attempt to check
  1167. X    the entry against the size rules.
  1168. X
  1169. X    If you have any suggestions, comments, fixes or complaints about
  1170. X    the mkentry.c program, please send Email to the judges.  (see below)
  1171. X
  1172. X    The following is a sample entry:
  1173. X
  1174. X---entry---
  1175. Xrule:    1992
  1176. Xtitle:    chonglab
  1177. Xentry:    0
  1178. Xdate:    Mon Feb 17 13:58:57 1992
  1179. Xhost:    Un*x v6, pdp11/45
  1180. X    2.9BSD, pdp11/70
  1181. X---remark---
  1182. X    This is a non-obfuscated obfuscated C program.
  1183. X
  1184. X    It is likely not to win a prize.  But what do you expect from
  1185. X    a short example!  (yes, Hello world progs have become old too)
  1186. X---author---
  1187. Xname:    Landon Curt Noll
  1188. Xorg:    IOCCC Judging Group
  1189. Xaddr:    Toad Hall
  1190. X    San Francisco, CA 94101
  1191. X    USA
  1192. Xemail:    chongo@toad.com
  1193. Xanon:    n
  1194. X---author---
  1195. Xname:    Larry Bassel
  1196. Xorg:    IOCCC Judging Group
  1197. Xaddr:    Toad Hall
  1198. X    San Francisco, CA 94101
  1199. X    USA
  1200. Xemail:    hoptoad!sun!lab
  1201. X    lab@sun.com
  1202. Xanon:    n
  1203. X---info---
  1204. Xbegin 444 info.file
  1205. XM2&$A("!792!G;W0@>6]U('1O(&QO;VLA"@I4:&%T('1H870@:7,L(&ES+@I4
  1206. XM:&%T('1H870@:7,@;F]T+`H@("`@:7,@;F]T('1H870@=&AA="!N;W0@:7,N
  1207. XM"E1H870@:7,L('1H870@=&AA="!I<R!N;W0L(&ES(0H*"0DM+2!C:&]N9V\@
  1208. X%,3DW-`H@
  1209. X`
  1210. Xend
  1211. X---build---
  1212. Xbegin 444 build
  1213. X28V,@<')O9RYC("UO('!R;V<*
  1214. X`
  1215. Xend
  1216. X---program---
  1217. Xbegin 444 prog.c
  1218. XC;6%I;B@I>W!R:6YT9B@B2&5L;&\L('=O<FQD(5QN(BD[?0H`
  1219. X`
  1220. Xend
  1221. X---end---
  1222. X
  1223. X    Where build uudecodes into:
  1224. X
  1225. Xcc prog.c -o prog
  1226. X
  1227. X    and prog.c uudecodes into:
  1228. X
  1229. Xmain(){printf("Hello, world!\n");}
  1230. X
  1231. X    Typically the build file should assume that the source is prog.c
  1232. X    and will compile into prog.  If an entry wins, we will rename
  1233. X    its source and binary to avoid filename collision.  By tradition,
  1234. X    we use the name of the entry's title, followed by an optional
  1235. X    digit in case of name conflicts.
  1236. X
  1237. X    If the above entry somehow won the 'least likely to win' award,
  1238. X    we would use chonglab.c and chonglab.
  1239. X
  1240. X    If your entry depends on, or requires that your build, source
  1241. X    and/or binary files be a particular name, please say so in the
  1242. X    ---remark--- section.  If this case applies, it would be be helpful
  1243. X    if you did one of the following:
  1244. X
  1245. X    * Tell us how to change the filename(s) in your entry.
  1246. X
  1247. X    * Have the build file make copies of the files.  For example:
  1248. X
  1249. X        cc prog.c -o special_name        need special binary
  1250. X
  1251. X        or  rm -f special_src.c            need special source
  1252. X        cp prog.c special_src.c
  1253. X        cc special_src.c -o special_name
  1254. X
  1255. X        or  rm -f special_build            need special build
  1256. X        tail +4 build > special_build
  1257. X        sh < special_build
  1258. X
  1259. X    * Assume that we will use the entry title.  Send us a version of 
  1260. X      your build/program files that uses the name convention.  You 
  1261. X      should uuencode these files in ---data--- sections.
  1262. X
  1263. X    If your entry needs to modify its source, info or binary files,
  1264. X    please say so in the ---remark--- section.  You should try to avoid
  1265. X    touching your original build, source and binary files.  You should
  1266. X    arrange to make copies of the files you intend to modify.  This
  1267. X    will allow people to re-generate your entry from scratch.
  1268. X
  1269. X    Remember that your entry may be built without a build file.  We
  1270. X    typically incorporate the build lines into a Makefile.  If the
  1271. X    build file must exist, say so in the ---remark--- section.
  1272. X
  1273. X    If your entry needs special info files, you should uuencode them
  1274. X    into ---info--- sections.  In the case of multiple info files,
  1275. X    use multiple ---info--- sections.  If no info files are needed,
  1276. X    then skip the ---info--- section.
  1277. X
  1278. X    Info files are intended to be input, or detailed information that
  1279. X    does not fit well into the ---remark--- section.  For example, an
  1280. X    entry that implements a compiler might want to provide some sample
  1281. X    programs for the user to compile.  An entry might want to include a
  1282. X    lengthly design document, that might not be appropriate for a
  1283. X    'hints' file.
  1284. X
  1285. X    Info files should be used only to supplement your entry.  For
  1286. X    example, info files may provide sample input or detailed
  1287. X    information about your entry.  Because they are supplemental,
  1288. X    the entry should not require them exist.
  1289. X
  1290. X    In some cases, your info files might be renamed to avoid name
  1291. X    conflicts.  If info files should not be renamed for some reason,
  1292. X    say so in the ---remark--- section.
  1293. X
  1294. X    Info files must uudecode into the current directory.  If they
  1295. X    absolutely must be renamed, or moved into a sub-directory, say
  1296. X    so in the ---remark--- section.
  1297. X
  1298. X
  1299. XJUDGING PROCESS:
  1300. X
  1301. X    Entries are judged by Larry Bassel and Landon Curt Noll.
  1302. X
  1303. X    Entries are unpacked into individual directories.  The Email message
  1304. X    is unpacked into individual files, each containing:
  1305. X
  1306. X    ---entry--- section
  1307. X    all ---author--- sections
  1308. X    all ---info--- sections
  1309. X    ---build--- section
  1310. X    ---program--- section
  1311. X    any other text, including the Email message headers
  1312. X
  1313. X    Prior to judging, the 'any other text' file is scanned to be sure
  1314. X    it does not contain useful information (or in case the entry was
  1315. X    malformed and did not unpack correctly).  Information from the
  1316. X    ---author--- sections are not read until the judging process is
  1317. X    complete, and then only from entries that have won an award.
  1318. X
  1319. X    The above process helps keep us biased for/against any one particular
  1320. X    individual.  We are usually kept in the dark as much as you are
  1321. X    until the final awards are given.  We like the surprise of finding
  1322. X    out in the end, who won and where they were from.
  1323. X
  1324. X    We attempt to keep all entries anonymous, unless they win an award.
  1325. X    Because the main 'prize' of winning is being announced, we make all
  1326. X    attempts to send non-winners into oblivion.  We remove all non-winning
  1327. X    files, and shred all related paper.  By tradition, we do not even
  1328. X    reveal the number of entries that we received.  (for the curious,
  1329. X    we do indicate the volume of paper consumed when presenting the IOCCC
  1330. X    winners at talks)
  1331. X
  1332. X    After the Usenix announcement, we attempt to send Email to the
  1333. X    authors of the winning entries.  One reason we do this is to give
  1334. X    the authors a chance to comment on the way we have presented their
  1335. X    entry.  They are given the chance to correct mistakes, typos.  We
  1336. X    often accept their suggestions/comments about our remarks as well.
  1337. X    This is done prior to posting the winners to the wide world.
  1338. X
  1339. X    Judging consists of a number of elimination rounds.  During a round,
  1340. X    the collection of entries are divided into two roughly equal piles;
  1341. X    the pile that advances on to the next round, and the pile that does
  1342. X    not.  We also re-examine the entries that were eliminated in the
  1343. X    previous round.  Thus, an entry gets at least two readings.
  1344. X
  1345. X    A reading consists of a number of actions:
  1346. X
  1347. X    * reading the ---entry--- section
  1348. X    * reading the uudecoded ---build--- section
  1349. X    * reading the uudecoded ---program--- section
  1350. X    * reading the uudecoded ---info--- section(s), if any
  1351. X    * passing the source thru the C pre-processor
  1352. X        shipping over any #include files
  1353. X    * performing a number of C beautify/cleanup edits on the source
  1354. X    * passing the beautified source thru the C pre-processor
  1355. X        shipping over any #include files
  1356. X
  1357. X    In later rounds, other actions are performed:
  1358. X
  1359. X    * linting the source
  1360. X    * compiling/building the source
  1361. X    * running the program
  1362. X    * performing misc tests on the source and binary
  1363. X
  1364. X    Until we reduce the stack of entries down to about 25 entries, entries
  1365. X    are judged on an individual basis.  An entry is set aside because it
  1366. X    does not, in our opinion, meet the standard established by the round.
  1367. X    When the number of entries thins to about 25 entries, we begin to form
  1368. X    award categories.  Entries begin to compete with each other for awards.
  1369. X    An entry often will compete in several categories.
  1370. X
  1371. X    The actual award category list will vary depending on the types of entries
  1372. X    we receive.  A typical category list might be:
  1373. X
  1374. X    * best small one line program
  1375. X    * best small program
  1376. X    * strangest/most creative source layout
  1377. X    * most useful obfuscated program
  1378. X    * best game that is obfuscated
  1379. X    * most creatively obfuscated program
  1380. X    * most deceptive C code
  1381. X    * best X client (see OUR LIKES AND DISLIKES)
  1382. X    * best abuse of ANSI C
  1383. X    * worst abuse of the rules
  1384. X    * <anything else so strange that it deserves an award>
  1385. X
  1386. X    We do not limit ourselves to this list.  For example, a few entries are so
  1387. X    good/bad that they are declared winners at the start of the final round.
  1388. X    We will invent awards categories for them, if necessary.
  1389. X
  1390. X    In the final round process, we perform the difficult tasks of
  1391. X    reducing the remaining entries (typically about 25) down to 8 or 10
  1392. X    winners.  Often we are confident that the entries that make it into
  1393. X    the final round are definitely better than the ones that do not
  1394. X    make it.  The selection of the winners out of the final round, is
  1395. X    less clear cut.
  1396. X
  1397. X    Sometimes a final round entry good enough to win, but is beat out
  1398. X    by a similar, but slightly better entry.  For this reason, it is
  1399. X    sometimes worthwhile to re-enter an entry that failed to win on a
  1400. X    previous year.  There have been winners that lost in a previous
  1401. X    year.  Of course, in those cases, improving on the entry made
  1402. X    the difference!
  1403. X
  1404. X    More often that not, we select a small entry (usually one line), a
  1405. X    strange/creative layout entry, and an entry that abuses the contest
  1406. X    rules in some way.
  1407. X
  1408. X    In the end, we traditionally pick one entry as 'best'.  Sometimes such
  1409. X    an entry simply far exceeds any of the other entry.  More often, the
  1410. X    'best' is picked because it does well in a number of categories.
  1411. X
  1412. X
  1413. XANNOUNCEMENT OF WINNERS:
  1414. X
  1415. X    The first announcement, occurs at a Summer Usenix conference.  By 
  1416. X    tradition, this is done during the latter part of the UUNET/IOCCC BOF, 
  1417. X    just prior to the Berkeley BSD, and BSDI BOF.
  1418. X
  1419. X    Winning entries will be posted in late June to the following groups:
  1420. X
  1421. X        comp.lang.c          comp.unix.wizards    alt.sources
  1422. X
  1423. X    In addition, pointers to these postings are posted to the following
  1424. X
  1425. X        comp.sources.d      alt.sources.d        misc.misc
  1426. X        comp.sources.misc
  1427. X
  1428. X    Winning entries will be deposited into the uunet archives.  See
  1429. X    below for details.
  1430. X
  1431. X    Often, winning entries are published in magazines such as "The C Users
  1432. X    Journal".  Winners have appeared in books ("The New Hackers Dictionary")
  1433. X    and on T-Shirts.
  1434. X
  1435. X    Last, but not least, winners receive international fame and flames!  :-)
  1436. X
  1437. X
  1438. XFOR MORE INFORMATION:
  1439. X
  1440. X    You may contact the judges by sending Email to the following address:
  1441. X
  1442. X    ...!{apple,pyramid,sun,uunet}!hoptoad!judges    (not the address for
  1443. X    judges@toad.com                     submitting entries)
  1444. X
  1445. X    Questions and comments about the contest are welcome.
  1446. X
  1447. X    One may obtain a copy of the current rules, guidelines or mkentry
  1448. X    program as well.  To stream line these common requests, we request
  1449. X    that you use the following subjects when making such requests:
  1450. X
  1451. X    subject          to request
  1452. X    -------          ----------
  1453. X    send rules      to obtain the current IOCCC rules
  1454. X    send guidelines      to obtain the current IOCCC guidelines
  1455. X    send mkentry      to obtain the current IOCCC mkentry program
  1456. X    send allinfo      to obtain the current IOCCC rules,guidelines,mkentry
  1457. X
  1458. X    One may also obtain the above items, we well as winners of previous
  1459. X    contests, via anonymous ftp from:
  1460. X
  1461. X    host: ftp.uu.net    (137.39.1.9)
  1462. X    user: anonymous
  1463. X    pass: yourname@yourhost
  1464. X    dir:  pub/ioccc
  1465. X
  1466. X    Often, contest rules, guidelines and winners are available from
  1467. X    archive sites.  Check comp.sources.unix archives, for example.
  1468. X    You may also request previous winners by Email, using the judges
  1469. X    Email address, though we ask that you do this as a last resort.
  1470. X
  1471. X
  1472. Xchongo <Landon Curt Noll> /\cc/\      hoptoad!chongo
  1473. XLarry Bassel                  {uunet,ucbvax,cbosgd}|sun!lab
  1474. END_OF_FILE
  1475.   if test 22215 -ne `wc -c <'1992/guidelines'`; then
  1476.     echo shar: \"'1992/guidelines'\" unpacked with wrong size!
  1477.   fi
  1478.   # end of '1992/guidelines'
  1479. fi
  1480. echo shar: End of archive 1 \(of 5\).
  1481. cp /dev/null ark1isdone
  1482. MISSING=""
  1483. for I in 1 2 3 4 5 ; do
  1484.     if test ! -f ark${I}isdone ; then
  1485.     MISSING="${MISSING} ${I}"
  1486.     fi
  1487. done
  1488. if test "${MISSING}" = "" ; then
  1489.     echo You have unpacked all 5 archives.
  1490.     rm -f ark[1-9]isdone
  1491. else
  1492.     echo You still must unpack the following archives:
  1493.     echo "        " ${MISSING}
  1494. fi
  1495. exit 0
  1496. exit 0 # Just in case...
  1497.