URI: 
       false.txt - brcon2024-hackathons - Bitreichcon 2024 Hackathons
  HTML git clone git://bitreich.org/brcon2024-hackathons git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/brcon2024-hackathons
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR Submodules
       ---
       false.txt (21173B)
       ---
            1 
            2                          The FALSE Programming Language
            3 
            4                            by Wouter van Oortmerssen
            5 
            6                                     Manual
            7 
            8 
            9 WHAT'S NEW in v1.3
           10 - lots of new and exciting example source code by lots of people!
           11   (have a look in `contrib/' for some amazing code)
           12 - documentation in french too
           13 - minor fixes and enhancements to the portable interpreter
           14   (read comments in the source)
           15 - new infos, ftp/www sites etc., read the last chapter
           16 
           17 WHAT'S NEW in v1.1
           18 - one bug fix in the 68k version
           19 - other example sources (mainly written by Eelko, in the "other" dir.)
           20 - Portable False Interpreter/Debugger!
           21   (read comments in the source)
           22 
           23 
           24 +-------------------------------+
           25 |        Introduction:                |
           26 +-------------------------------+
           27 
           28 The language FALSE and it's compiler were designed for only two reasons:
           29 - building a working compiler in just 1k (!)
           30 - designing a language that looks cryptic and fuzzy (in the APL tradition)
           31 
           32 the result is a language that is quite powerfull (for it's size).
           33 It's a Forth type language with lambda abstraction and lots of other goodies.
           34 I named the language after my favourite truthvalue.
           35 
           36 NOTE: a) the compiler as well as the generated code need kickstart v37+
           37       b) You're strongly advised to read this entire manual before
           38          trying to operate the compiler.
           39 
           40 +-------------------------------+
           41 |        The implementation:        |
           42 +-------------------------------+
           43 
           44 To compile a FALSE program, type "false" followed by the source-code
           45 name, like:
           46 
           47 1> false helloworld.f
           48 
           49 the compiler produces an executable called "a.out" in the same dir:
           50 
           51 1> a.out
           52 Hello, World!
           53 1>
           54 
           55 To squeeze the real compilation functions for all language elements in
           56 1024 bytes, some things had to go: there are no error messages, and even
           57 worse: there are no syntax error checks. Luckily, the language is
           58 designed so that it's hard to make compile-time errors.
           59 
           60 the compiler only signals an error in the following events:
           61 - it could not allocate memory
           62 - it could not read the source file
           63 - it could not write the executable
           64 - it could not open dos.library (very unlikely)
           65 - it found a symbol in the source, which isn't part of the language.
           66 
           67 an error is signalled by returning value 10 instead of 0, it is
           68 therefore wise to have your cli-prompt display return values ("%R")
           69 
           70 note: the compiler will start acting weird as soon as you try
           71 to compile sources or produce executables >32k
           72 
           73 Working with FALSE
           74 ------------------
           75 It is actually possible to write small utilities and stuff in FALSE,
           76 and quite powerfull too once you see how to use stacks and lambda
           77 functions etc. However, with a minimal compiler like this it's hard to
           78 find errors, and I suppose you really have to be a Forth hacker or a
           79 hardcore programmer to get the most of it.
           80 
           81 Helloworld in FALSE:
           82 --------------------
           83 
           84 "Hello, World!
           85 "
           86 
           87 (yes, that's all...).
           88 And this is the fac() function definition in FALSE:
           89 
           90 [$1=$[\%1\]?~[$1-f;!*]?]f:
           91 
           92 (fuzzy eh? we'll explain that later...)
           93 
           94 
           95 +-------------------------------+
           96 |        FALSE: The Language.        |
           97 +-------------------------------+
           98 
           99 Format of the language:
          100 -----------------------
          101 FALSE sources are totally free-format, i.e you may have any number
          102 of tabs/spaces/lf's between two symbols. comments start with "{",
          103 end with "}" and may not be nested.
          104 
          105 
          106 evaluation:
          107 -----------
          108 FALSE inherits its way of evaluating expressions from Forth, so it
          109 really helps if you know that language, but for those who don't:
          110 
          111 All elements in the language are defined by what they push on and/or
          112 pop from the stack. for example, a number like "1" or "100" simply
          113 pushes it's own value on the stack. An operator like "+" takes the
          114 two top elements of the stack, adds them, and pushes back the result:
          115 
          116 1 2 + 4 *        { (1+2)*4 }
          117 
          118 the result of this expression is "12". We will use the notation
          119 (<pops>-<pushes>) to signify what a function does, so "1" does (-num)
          120 and "+" does (n1,n2-result)
          121 
          122 complex expressions will keep lots of intermediate results on the stack,
          123 so mostly there's no need for local variables. FALSE doesn't even
          124 have expressions or statements; more likely a program is one stream
          125 of symbols that  manipulate the stack. It's very helpfull when you
          126 can imagine what the stack looks like in a particular part of the program
          127 when programming.
          128 
          129 
          130 elementary functions:
          131 ---------------------
          132 
          133 available are:
          134 
          135 "+"        "-"        "*"        "/"        "_"
          136 
          137 these function as usual. "_" is the unary minus.
          138 
          139 
          140 "="        ">"
          141 
          142 these result in 0 (false) or -1 (true)
          143 
          144 unequal is "=~", and smaller than etc. can be made by swapping arguments
          145 and/or using "~"
          146 
          147 example:        a;1_=~                { a<>-1 }
          148 
          149 
          150 "&"        "|"        "~"
          151 
          152 "and", "or" and "not", as usual.
          153 
          154 example:        a;0>a;99>~&        { (a>0) and (a<100) }
          155 
          156 
          157 values:
          158 -------
          159 
          160 values are either integers like discussed before ("1", "100" etc.),
          161 or characters precede by a quote: 'A (equals 65) (do not mix up with
          162 backquote "`" !)
          163 note that the 1k parser only parses integers up to 320000, it uses
          164 full 32bit representation for them, however.
          165 
          166 
          167 global variables:
          168 -----------------
          169 variables to store values are less needed in FALSE than in other
          170 languages. in FALSE they are used mostly for functions, explained
          171 below.
          172 
          173 a variable is a character "a" to "z" (just these).
          174 ":" is the assignment function, and ";" is contrary: it gets the
          175 variable's value:
          176 
          177 1a:        { a:=1 }
          178 a;1+b:        { b:=a+1 }
          179 
          180 i.e: "a;" is used where in other languages you would just write "a"
          181 
          182 all variables (and also stack-items) are 32bits.
          183 
          184 lambda functions:
          185 -----------------
          186 a FALSE lambda function is a piece of code between []. for example:
          187 
          188 [1+]
          189 
          190 is a function that adds 1 to it's argument. A function is really defined
          191 by what it takes from the stack (in this case the first arg to "+"), and
          192 what it puts back, just like builtin functions. Note that FALSE lambda
          193 functions are not restricted to just one return value.
          194 
          195 what a [] expression really does, is push the function. this means in
          196 practise that it can be given to yet another function as argument etc.,
          197 just like in functional languages. The symbol "!" is called "apply",
          198 and applies a function to it's arguments, for example:
          199 
          200 2[1+]!
          201 
          202 would result in "3"
          203 This wouldn't make much sense, since what you really want is define the
          204 function once, and then use it all-over. this is easy:
          205 
          206 [1+]i:
          207 
          208 this defines the function "i" (actually, it assigns the function to "i"),
          209 so that it can be used simply by applying "i" to it's arguments:
          210 
          211 2i;!
          212 
          213 WARNING: as with all other elements in FALSE, but even more important
          214          with functions: the 1k compiler does not check if symbols like
          215          "!" really get a function as argument (so "1!" means trouble),
          216          the compiler may even crash if you don't balance your [ and ].
          217 
          218 
          219 stack functions:
          220 ----------------
          221 
          222 "$"        (x-x,x)                        dup:        duplicate topmost stackitem
          223 "%"        (x-)                        drop:        delete topmost stack item
          224 "\"        (x1,x2-x2,x1)                swap:        swap to topmost stack-items.
          225 "@"        (x,x1,x2-x1,x2,x)        rot:        rotate 3rd stack item to top.
          226 "ø"        (n-x)                        pick:        copy n-th item to top (0ø equals $)
          227 
          228 examples:
          229 
          230 1$                equals                1 1
          231 1 2%                equals                1
          232 1 2\                equals                2 1
          233 1 2 3@                equals                2 3 1
          234 7 8 9 2ø        equals                7 8 9 7
          235 
          236 
          237 control structure:
          238 ------------------
          239 FALSE only has an IF and a WHILE.
          240 if is "?", and looks like this: (bool,fun-). example:
          241 
          242 a;1=["hello!"]?                { if a=1 then print "hello!" }
          243 
          244 the first argument is a boolean value, the second the lambda function
          245 to be executed (see below for "")
          246 there's no "else", so you'll have to mimic this with a second "?".
          247 this can be easily done by copying the truthvalue:
          248 
          249 a;1=$["true"]?~["false"]?
          250 
          251 after the first "?" (wether it's executed or not), a copy of the truthvalue
          252 is still on the stack, and we negate it for the else part.
          253 Beware that if the first "if" needs arguments on the stack from before
          254 the boolean expression, it's top is still the truthvalue.
          255 
          256 While is a "#", and gets two lambda functions as args, one that results in
          257 a boolean, and the second as body:
          258 
          259 [a;1=][2f;!]#                { while a=1 do f(2) }
          260 
          261 note that with while, if and lambda's, you can build virtually
          262 any other control structure.
          263 
          264 
          265 Input/Output:
          266 -------------
          267   watch out: all these are BUFFERED.
          268 
          269 - strings printing: strings simply print themselves. Special: strings in FALSE
          270   may contain <lf>'s, that explains why in the helloworld program, the second
          271   " is on the next line:
          272 
          273   "Hello, World!
          274   "
          275 
          276 - integers: "." prints the topmost stack item as integer value:
          277 
          278   123.                { prints string "123" on console }
          279 
          280 - characters: ","
          281 
          282   65,                { prints "A" }
          283 
          284 - reading a character from stdin: "^"
          285 
          286   ^                { top stack is char read }
          287 
          288 - flush: "ß"
          289   when stdin and stdout are different (i.e. you started your compiled
          290   FALSE program with <infile >outfile you will hardly need to flush, however,
          291   if you both use "^" and the output operations on the same console,
          292   you may need to flush between input and output.
          293   "ß" flushes both input and output.
          294 
          295   ß[^$1_=~][,]#                { while c:=getc()<>EOF do putc(c) }
          296 
          297   for example, above program copies input to output until eof,
          298   so no flushing is needed after every read when used with two
          299   files, however:
          300 
          301   "press return:"ß^%ß"continuing..."
          302 
          303   it is, since we get input on the same console as the output.
          304 
          305 
          306 +-------------------------------+
          307 |        Example programming        |
          308 +-------------------------------+
          309 
          310 How the $#%! am I going to write a decent program with all this, you may ask.
          311 Well, the first barrier one has to take into account, is that FALSE doesn't
          312 support any amiga-specific programming, some io-functions is as far as
          313 it gets. However, with those, you can create some stunningly compact
          314 utilities, for example the FALSE version of the "copy" command we saw above,
          315 in just 13 bytes!
          316 
          317 ß[^$1_=~][,]#
          318 
          319 ok, what happens: first recognise the four main parts in this program,
          320 we have a flush, then two arguments and then a while. The first []
          321 function is supposed to deliver the boolean for the while: it reads
          322 a character, duplicates it, the compares it it with -1 (EOF). at the end
          323 of this function, we do not only have a boolean, but also an extra copy
          324 of the character we read. This immediately demonstrates a powerfull
          325 feature of FALSE: we can have any number of interim-results on the
          326 stack. the body of the while loop [,] just prints the character to
          327 stdout.
          328 Note that if the body is not executed, we leave with a non-empty stack.
          329 This is no problem at the end of a program, however, doing this within an
          330 iteration would be fatal.
          331 
          332 
          333 another example of FALSE programming: the fac() function.
          334 
          335 [$1=$[\%1\]?~[$1-f;!*]?]f:
          336 
          337 thus we call fac(6) (=720) like:
          338 
          339 6f;!
          340 
          341 no range checking is done by the "f" function, that is what
          342 is done by the fac.f example program.
          343 
          344 Well, how does it work? (does it?) First recognise the f;! within
          345 the function implementation: that's the recursion. Let us recall what
          346 fac() looks like in a hypotheticall procedural/functional programming
          347 language:
          348 
          349 fac(n) = if n=1 then 1 else n*fac(n-1)
          350 
          351 our FALSE code goes just along these lines, only we use two "if"'s (hence
          352 the two [] blocks) insteas of one if-then-else.
          353 we start with (n-) on the stack:
          354 
          355 $1=$
          356 
          357 duplicate the n, and compare it with 1, and leave a second truthvalue (t),
          358 thus: (n,t,t-)
          359 
          360 [\%1\]?
          361 
          362 first push the [], and after the "if" (=?) we have (n,t-). we won't
          363 be needing the lower n anymore, so we swap and drop. then we push the
          364 final result "1", and swap it below the truthvalue for the second "if".
          365 (1,t-)
          366 
          367 ~[$1-f;!*]?
          368 
          369 we first have to negate the truthvalue, because this is the else part.
          370 in the "if"-body, we have just (n-), and we add a "n-1" to that as argument
          371 for the recusive call. after f;! we have (n,r-) (r is result of the call),
          372 and we simply multiply the two together as result of the whole.
          373 
          374 this may look all awfully complicated, but infact, it isn't. it's
          375 just a very different style of programming. once you fully understand
          376 it's power, you won't want to live without it :-)
          377 
          378 if by now you haven't understood zip of how FALSE works, this probably
          379 isn't the language for you. however, if you got the slightest feeling
          380 that some things are getting clear to you, try understanding the examples,
          381 and your on your way of becoming a real FALSE programmer ! :-). however,
          382 the examples are not heavily commented, as that is considered bad-taste
          383 in FALSE (see some section below).
          384 
          385 
          386 +-------------------------------+
          387 |        FALSE wizards corner        |
          388 +-------------------------------+
          389 
          390 "Inline assembly" in FALSE:
          391 ---------------------------
          392 
          393 one topic has been kept undiscussed (on purpose), and it's the
          394 possibility to add assembly code to a FALSE program, to allow it to
          395 be extended with custom functions.
          396 
          397 syntax:                <integer>`
          398 
          399 any integer value 0..65535 folowed by a backquote. an expression like
          400 this causes the a 16bit value to be put directly into the code.
          401 A series of backquoted values may allow you a primitive form of
          402 inline assembly. for example:
          403 
          404 [8221`29184`9336`4`50510`20142`65338`50510`11008`]a:        { allocmem (size-mem) }
          405 [8221`8797`9336`4`50510`20142`65326`50510`]f:                { freemem (mem,size-) }
          406 
          407 are two assembly functions that allow you to allocate memory
          408 from within FALSE (see example alloc.f)
          409 
          410 register conventions:
          411 when writing assembly code for use with FALSE, use following registers:
          412 
          413 A6 = dosbase
          414 A5 = evaluation stack. use MOVE.L (A5)+,D0 to read a paramenter into D0,
          415      and MOVE.L D0,-(A5) to write one.
          416 A4 = variables. 0(A4) = a, 4(A4) = b etc.
          417 D6 = stdout
          418 D5 = stdin
          419 
          420 example code for allocmem/freemem above:
          421 
          422 alloc:        move.l        (a5)+,d0
          423         moveq        #0,d1
          424         move.l        4.w,a2
          425         exg        a2,a6                ; we need to restore dosbase later.
          426         jsr        -198(a6)
          427         exg        a2,a6
          428         move.l        d0,-(a5)        ; no rts, that's done by []
          429 
          430 free:        move.l        (a5)+,d0        ; second argument first!
          431         move.l        (a5)+,a1
          432         move.l        4.w,a2
          433         exg        a2,a6
          434         jsr        -210(a6)
          435         exg        a2,a6
          436 
          437 
          438 peek/poke:
          439 ----------
          440 
          441 ":" and ";" are operators to read and write variables, but they can be
          442 (mis-)used to do arbitrary peek and poking, even array-indexing!
          443 (see vcheck.f for an example: we read execbase)
          444 
          445 array indexing and structure reading:
          446 if p is a pointer to an array/structure, then:
          447 
          448 p;<index>+;
          449 
          450 reads p[<index>].
          451 
          452 unfortunately, this way you can only read 32bit values.
          453 
          454 cli arguments:
          455 --------------
          456 
          457 reading files is mostly done with redirection on the commandline, however,
          458 for future extensability, a pointer to the command-line arguments is
          459 passed in var a. see also "command line tips" below.
          460 
          461 stack:
          462 ------
          463 
          464 you can use the stack as a buffer, and reverse-indexing the values
          465 on it with ø. however, the FALSE stack is the lower-half of the normal
          466 amigados stack, and thus normally only 2k. You can write programs
          467 that need arbitrarily large stack-buffers by increasing the stack
          468 size before running.
          469 
          470 command line tips:
          471 ------------------
          472 
          473 - make sure you write an input redirection when testing some
          474   programs: if the program simply does "nothing", than the
          475   computer is not hung, but it's simply waiting for input.
          476 - if you do not write a flush (ß) at the start of a program that
          477   processes the input to the output, you will get a <lf> as
          478   first input: this is actually the commandline. example:
          479 
          480   a.out blabla <in >out
          481 
          482   then a.out will first read "blabla" as a line, then the contents
          483   of "in".
          484 
          485 
          486 good style:
          487 -----------
          488 
          489 programming in FALSE has a certain kind of taste: it's not easy, but
          490 when it works, it works good, and the resulting sources look great.
          491 Therefore, it may be tempting to "indent" while-loops in larger
          492 programs, but remember:
          493 - indentation, spacing and comments are for wimps :-)
          494 - real FALSE programmmers:
          495   - write dense code
          496   - write only very "global" comments.
          497   - use the stack intensively, and thus dislike to use variables
          498     for other purposes than function definitions.
          499 
          500 
          501 
          502 +---------------------------------------+
          503 |        FALSE language overview.        |
          504 +---------------------------------------+
          505 
          506 syntax:                pops:                pushes:                example:
          507                 -->top                -->top
          508 --------------- --------------- --------------- -------------------------------
          509 
          510 {comment}        -                -                        { this is a comment }
          511 [code]                -                function        [1+]        { (lambda (x) (+ x 1)) }
          512 a .. z                -                varadr                a        { use a: or a; }
          513 integer                -                value                1
          514 'char                -                value                'A        { 65 }
          515 num`                -                -                0`        { emitword(0) }
          516 
          517 :                n,varadr        -                1a:        { a:=1 }
          518 ;                varadr                varvalue        a;        { a }
          519 !                function        -                f;!        { f() }
          520 
          521 +                n1,n1                n1+n2                1 2+        { 1+2 }
          522 -                n1,n2                n1-n2                1 2-
          523 *                n1,n2                n1*n2                1 2*
          524 /                n1,n2                n1/n2                1 2/
          525 _                n                -n                1_        { -1 }
          526 
          527 =                n1,n1                n1=n2                1 2=~        { 1<>2 }
          528 >                n1,n2                n1>n2                1 2>
          529 
          530 &                n1,n2                n1 and n2        1 2&        { 1 and 2 }
          531 |                n1,n2                n1 or n2        1 2|
          532 ~                n                not n                0~        { -1,TRUE }
          533 
          534 $                n                n,n                1$        { dupl. top stack }
          535 %                n                -                1%        { del. top stack }
          536 \                n1,n2                n2,n1                1 2\        { swap }
          537 @                n,n1,n2                n1,n2,n                1 2 3@        { rot }
          538 ø (alt-o)        n                v                1 2 1ø        { pick }
          539 
          540 
          541 ?                bool,fun        -                a;2=[1f;!]?
          542                                                 { if a=2 then f(1) }
          543 #                boolf,fun        -                1[$100<][1+]#
          544                                                 { while a<100 do a:=a+1 }
          545 
          546 .                n                -                1.        { printnum(1) }
          547 "string"        -                -                "hi!"        { printstr("hi!") }
          548 ,                ch                -                10,        { putc(10) }
          549 ^                -                ch                ^        { getc() }
          550 ß (alt-s)        -                -                ß        { flush() }
          551 
          552 
          553 
          554 +-----------------------------------------------+
          555 |        additional infos & thank you's                |
          556 +-----------------------------------------------+
          557 
          558 FALSE was created for fun, just to see how small a compiler I could
          559 write while still compiling a relatively powerfull language.
          560 The result is even better than I thought: it's great fun to
          561 program in FALSE, and it looks even better.
          562 
          563 about the compiler source: note that throughout the program ALL
          564 variables reside in registers without saving on the stack!
          565 please: don't come and tell me you found a way to reduce
          566 the size of the executable by 4 more bytes... I think it's small
          567 enough as it is now.
          568 
          569 False has inspired other people to implement similarly perverse
          570 languages. Some of them are:
          571 
          572 * "Brainfuck" by Urban Mueller. If you enjoy compilers just because
          573   of their lenght, make sure you get a look at the this! (an
          574   executable in less than 256 bytes!) [aminet:dev/lang/brainfuck2.lha]
          575   This is helloworld:
          576 
          577   >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]
          578   <.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[
          579   <++++>-]<+.[-]++++++++++.
          580 
          581 * "Y" by Thomas Fischbacher. Very similar to False (syntax too), yet
          582   with some more powerful constructs. Comes with (portable) interpreter
          583   in C++ [aminet:dev/lang/Y.lha]
          584 
          585 * "Befunge" by Chris Pressey. Comes with interpreter and debugger in C.
          586   Code is different from False, but looks equally beautiful. [bef.zip,
          587   have a look at http://www.cats-eye.com/cet/soft/lang/befunge/].
          588   factorial looks like this:
          589 
          590                                       v
          591   >v"Please enter a number (1-16) : "0<
          592   ,:             >$*99g1-:99p#v_.25*,@
          593   ^_&:1-99p>:1-:!|10          < 
          594            ^     <
          595               
          596 * "Bloop" by Ben Schaeffer <Yaxman@nesbbx.rain.com>. An as yet unreleased
          597   language with features from False (and another pet language of mine,
          598   "Yax"). Ben also made a true x86 version of False (by translating the
          599   68k code), but I lost the code (silly me).
          600 
          601 
          602 Steinar Knutsen has been so friendly to set up an FTP site so
          603 all you people can put your False related products there!
          604 
          605 ftp://ftp.nvg.unit.no/pub/lang/false/ for the distribution.
          606 ftp://ftp.nvg.unit.no/pub/lang/false/src/ for sources not in the
          607 distribution.
          608 
          609 
          610 Chris Pressey has a False homepage at:
          611 
          612 http://www.cats-eye.com/cet/soft/lang/false/
          613 
          614 
          615 
          616 I want to thank the people who contributed sourcecode,
          617 among others:
          618 
          619 Ben Schaeffer, Ed Mackey, Eelko de Vos (and the rest of The TU-Delft
          620 False Fanclub, Maarten and Rene), Herb Wollman, Lionel Vintenat,
          621 Marcel van Kervinck, Peter Bengtsson, Steinar Knutsen, Thomas Fischbacher,
          622 and Tomas Partl
          623 
          624 and the many more people that have shown their interest
          625 in the language. one of them put it like this:
          626 
          627   #define FLAME ON
          628   Dear Mr. Wouter van Oortmerssen, Sir, Bwana!
          629   
          630   We (FORTH enthusiasts of Southern German Banana Republic
          631   of Bavaria) are not amused by your FALSE language.
          632   
          633   No Sir, not at all.
          634   
          635   Some of us are still jumping up and down in the coconut tree
          636   muttering obscenities like "DUP RECURSE that *@! Oortmerssen!".
          637   (Some are say even things like "'Oortmerssen EXECUTE")
          638   
          639   You have had the intention of writing an absolutely cryptic
          640   while extreme terse & powerful language. In that you've
          641   succeeded marvelously.
          642   Yet why, Great Moore! have you taken FORTH for the template?
          643   Forth is quite cryptic already, yet you must you render it
          644   completely unreadable. In Bavaria this is regarded as a
          645   grave public offense, sentenceable to not below of 3 years
          646   of pure K&R C programming. You could plead for clemency by
          647   pointing out your having introduced the lambda computational
          648   concept into FORTH, though.
          649   I will grant you that much.
          650 
          651 Donations? who would want to give something for a program that
          652 has the size of a bootblock virus? anyway, the only thing I'd
          653 like to receive is large and complex FALSE sources (of working
          654 applications, of course). Please always put a comment at the
          655 top of your source, otherwise you'll give me a hard time guessing
          656 if it's FALSE or uuencoded. don't ask me to debug your code, as
          657 understanding other peoples FALSE programs is horrible.
          658 
          659 If you want to contact me:
          660 
          661 
          662         Wouter van Oortmerssen
          663         Levendaal 87
          664         2311 JG  Leiden
          665         HOLLAND
          666 
          667 or better if you have access to Email:
          668 
          669         Wouter@mars.let.uva.nl
          670         W.v.Oortmerssen@let.uva.nl
          671         Oortmers@fwi.uva.nl
          672