From 85ddf1a25a472520dd1112ff8d67df9e31b546ce Mon Sep 17 00:00:00 2001 From: Cody Boone Ferguson <53008573+xexyl@users.noreply.github.com> Date: Tue, 28 Mar 2023 08:22:51 -0700 Subject: [PATCH] Fixes in 1992/buzzard.2/README.md Typo/spelling fixes and formatting fixes. --- 1992/buzzard.2/README.md | 324 ++++++++++++++++++++------------------- 1 file changed, 164 insertions(+), 160 deletions(-) diff --git a/1992/buzzard.2/README.md b/1992/buzzard.2/README.md index d4e178418..a2e82cfe0 100644 --- a/1992/buzzard.2/README.md +++ b/1992/buzzard.2/README.md @@ -10,29 +10,32 @@ make all -### To run +## To run: - First: +First: make first - Second: +Second: echo help | cat third help.th - | ./first cat third demo5.th | ./first - Third: +Third: cat third help.th - | ./first - NOTE: Wait until Ok is printed and the type: - 2 3 + . cr <-- yes you should really type the 2 letters: cr +NOTE: Wait until Ok is printed and the type: - Forth: + 2 3 + . cr + +Yes you should really type the 2 letters: cr. + +Fourth: Sorry, this is third! -### Alternate code +## Alternate code: An alternate version of this entry, `buzzard.2.alt.c`, is provided. This alternate code does not contain a fix that the author notes below. @@ -45,191 +48,192 @@ Use `buzzard.2.alt` as you would `buzzard.2` above. ## Judges' comments - Have fun! +Have fun! ## Author's comments - What it does: +What it does: - first implements a relatively primitive stack machine. How - primitive? It supplies 13 visible primitives: 3 arithmetic, - 1 comparison, 2 memory-access, 2 character I/O, 3 primitives - for defining new words, 1 tokenizing, and 1 special stack - operation. (There are also three internal operations for - the stack machine: 'push this integer', 'call this code', - and 'compile a call to this code'.) +`first` implements a relatively primitive stack machine. How +primitive? It supplies 13 visible primitives: 3 arithmetic, +1 comparison, 2 memory-access, 2 character I/O, 3 primitives +for defining new words, 1 tokenizing, and 1 special stack +operation. (There are also three internal operations for +the stack machine: 'push this integer', 'call this code', +and 'compile a call to this code'.) - It is very difficult to accomplish anything with this set - of primitives, but they do have an interesting property. +It is very difficult to accomplish anything with this set +of primitives, but they do have an interesting property. - This--what this interesting property is, or in other words - what first is good for--is the major obfuscation; there are - also minor source obfuscations, as well as some design tricks - that are effectively obfuscations. Details on the obfuscations - are below, and the interesting property is discussed much - further down. +This--what this interesting property is, or in other words +what first is good for--is the major obfuscation; there are +also minor source obfuscations, as well as some design tricks +that are effectively obfuscations. Details on the obfuscations +are below, and the interesting property is discussed much +further down. - How to run it: +### How to run it: - first expects you to first enter the names of the 13 primitives, - separated by whitespace--it doesn't care what you name them, but - if all the names aren't unique, you won't be able to use some of - them. After this you may type any sequence of valid first input. - Valid first input is defined as any sequence of whitespace-delimited - tokens which consist of primitives, new words you've defined, and - integers (as parsed by "%d"). Invalid input behaves unpredictably, - but gives no warning messages. A sample program, demo1.1st, is - included, but it only works on ASCII systems. +`first` expects you to first enter the names of the 13 primitives, +separated by whitespace--it doesn't care what you name them, but +if all the names aren't unique, you won't be able to use some of +them. After this you may type any sequence of valid first input. +Valid first input is defined as any sequence of whitespace-delimited +tokens which consist of primitives, new words you've defined, and +integers (as parsed by `"%d"`). Invalid input behaves unpredictably, +but gives no warning messages. A sample program, `demo1.1st`, is +included, but it only works on ASCII systems. - Do not expect to be able to do anything interesting with first. +Do not expect to be able to do anything interesting with first. - To do something interesting, you need to feed first the file - third first. In unix, you can do +To do something interesting, you need to feed first the file +third first. In unix, you can do - % cat third help.th - | first + % cat third help.th - | ./first - to do this. Hopefully most operating systems will provide a - way to do this. It may take some time for this to complete - (I seem to remember it taking several minutes on an 8086 PC); - THIRD will prompt you when it is finished. The file third has - not been obfuscated, due to sheer kindness on the author's part. +to do this. Hopefully most operating systems will provide a +way to do this. It may take some time for this to complete +(I seem to remember it taking several minutes on an 8086 PC); +THIRD will prompt you when it is finished. The file third has +not been obfuscated, due to sheer kindness on the author's part. - For more information on what you can do once you've piped - THIRD into first, type 'help' and consult FORTH manuals for - further reference. Six sample THIRD programs are included - in the files demo[1-6].th. buzzard.2.README has more - information. +For more information on what you can do once you've piped +THIRD into first, type 'help' and consult FORTH manuals for +further reference. Six sample THIRD programs are included +in the files demo[1-6].th. buzzard.2.README has more +information. - Keep in mind that you are still running first, and - are for the most part limited by first's tokenizer - (notably, unknown words will attempt to be parsed as - integers.) It is possible to build a new parser that - parses by hand, reading a single character at a time; - however, such a parser cannot easily use the existing - dictionary, and so would have to implement its own, - thus requiring reimplementing all of first and third - a second time--I did not care to tackle this project. +Keep in mind that you are still running first, and +are for the most part limited by first's tokenizer +(notably, unknown words will attempt to be parsed as +integers.) It is possible to build a new parser that +parses by hand, reading a single character at a time; +however, such a parser cannot easily use the existing +dictionary, and so would have to implement its own, +thus requiring reimplementing all of first and third +a second time--I did not care to tackle this project. - Compiling: +### Compiling: - first is reasonably portable. You may need to adjust the - size of the buffers on smaller machines; m[] needs to be - at least 2000 long, though. +`first` is reasonably portable. You may need to adjust the +size of the buffers on smaller machines; `m[]` needs to be +at least 2000 long, though. - I say first is portable mainly because it uses native types. - Unlike FORTH, which traditionally allows byte and multi-byte - operations, all operations are performed on C 'int's. That - means first code is only as portable as the same code would - be in C. As in C, the result of dividing -1 by 2 is machine - (or rather compiler) dependent. +I say `first` is portable mainly because it uses native types. +Unlike FORTH, which traditionally allows byte and multi-byte +operations, all operations are performed on C `int`s. That +means first code is only as portable as the same code would +be in C. As in C, the result of dividing -1 by 2 is machine +(or rather compiler) dependent. - How is first obfuscated? +### How is first obfuscated? - first is obfuscated in several ways. Some minor obfuscations - like &w[&m[1]][s] for s+m[w+1] were in the original source - but are no longer because, apparently, ANSI doesn't allow it - (gcc -ansi -pedantic doesn't mind it, though.) - Other related obfuscations are still present. The top of the - stack is cached in a variable, which increases performance - massively if the compiler can figure out to keep it in a register; - it also obfuscates the code. (Unfortunately, the top of stack - is a global variable and neither gcc nor most bundled compilers - seem to register allocate it.) +`first` is obfuscated in several ways. Some minor obfuscations +like `&w[&m[1]][s]` for `s+m[w+1]` were in the original source +but are no longer because, apparently, ANSI doesn't allow it +(gcc -ansi -pedantic doesn't mind it, though.) +Other related obfuscations are still present. The top of the +stack is cached in a variable, which increases performance +massively if the compiler can figure out to keep it in a register; +it also obfuscates the code. (Unfortunately, the top of stack +is a global variable and neither gcc nor most bundled compilers +seem to register allocate it.) - More significant are the design obfuscations. m[0] is the - "dictionary pointer", used when compiling words, and m[1] is - the return stack index. Both are used as integer offsets into - m. Both are kept in m, instead of as separate pointers, - because they are then accessible to first programs, which is a - crucial property of first. Similarly the way words are stored - in the dictionary is not obvious, so it can be difficult to - follow exactly what the compiler words are doing. +More significant are the design obfuscations. `m[0]` is the +"dictionary pointer", used when compiling words, and `m[1]` is +the return stack index. Both are used as integer offsets into +m. Both are kept in m, instead of as separate pointers, +because they are then accessible to first programs, which is a +crucial property of first. Similarly the way words are stored +in the dictionary is not obvious, so it can be difficult to +follow exactly what the compiler words are doing. - Assuming you've waded through all that, you still have - to penetrate the most significant obfuscation. Traditionally, - the question is whether a reader can answer the question "what - will this do when I run it". A reader who has deciphered first - to this point may think they know the answer to this question, - but they may not know the answer to the more important question, - "what will this program do when given the right input?" FORTH - afficianados, and especially FORTH implementors, may recognize - the similarity of the internal compiler format to many FORTH - interal representations, and, being aware that FORTH interpreters - can often by self-compiling, may be suspicious that this program - can compile FORTH, or a significant subset of it, or at least be - capable of doing so if fed the right input. Of course, the name - "THIRD" should be a dead giveaway, if the name "first" wasn't. - (These numbers were largely chosed because they were five letters - long, like "FORTH", and would not require truncation to five - letters, which would be a dead giveaway. Besides, THIRD represents - a step backwards, in more ways than one.) +Assuming you've waded through all that, you still have +to penetrate the most significant obfuscation. Traditionally, +the question is whether a reader can answer the question "what +will this do when I run it". A reader who has deciphered first +to this point may think they know the answer to this question, +but they may not know the answer to the more important question, +"what will this program do when given the right input?" FORTH +aficionados, and especially FORTH implementers, may recognize +the similarity of the internal compiler format to many FORTH +internal representations, and, being aware that FORTH interpreters +can often by self-compiling, may be suspicious that this program +can compile FORTH, or a significant subset of it, or at least be +capable of doing so if fed the right input. Of course, the name +"THIRD" should be a dead giveaway, if the name "first" wasn't. +(These numbers were largely chosen because they were five letters +long, like "FORTH", and would not require truncation to five +letters, which would be a dead giveaway. Besides, THIRD represents +a step backwards, in more ways than one.) - What exactly is first, then? +### What exactly is `first`, then? - first is a tiny interpreter which implements a sufficient - pseudo-subset of FORTH to allow it to bootstrap a relatively - complete version of FORTH (based loosely on forth79), which - I call THIRD. Complete relative to what, I'm not sure. +`first` is a tiny interpreter which implements a sufficient +pseudo-subset of FORTH to allow it to bootstrap a relatively +complete version of FORTH (based loosely on forth79), which +I call THIRD. Complete relative to what, I'm not sure. - I believe first is close to the smallest amount of code possible - to get this effect *using forth-style primitives*, and still have - some efficiency (it is possible to get by without multiplication - if you have addition, obviously). In the design file, design, - I give a justification for why each primitive in first was included. +I believe first is close to the smallest amount of code possible +to get this effect *using forth-style primitives*, and still have +some efficiency (it is possible to get by without multiplication +if you have addition, obviously). In the design file, design, +I give a justification for why each primitive in first was included. - THIRD is sorta slow, because first has so few primitives that - many things that are primitives in FORTH (like swap) take a - significant amount of time in THIRD. +THIRD is sorta slow, because first has so few primitives that +many things that are primitives in FORTH (like swap) take a +significant amount of time in THIRD. - When you get the 'Ok.' message from third, try out some sample - FORTH code (first has no way of knowing if keyboard input is - waiting, so it can't actually prompt you in a normal way. It - only prints 'Ok.' after you define a word). - - 2 3 + . cr ( add 2 and 3, and print it and a newline.) - - and THIRD responds - - 5 - - Now try: - - : test 11 1 do i . loop cr ; - test - - and THIRD responds - - 1 2 3 4 5 6 7 8 9 10 +When you get the 'Ok.' message from third, try out some sample +FORTH code (first has no way of knowing if keyboard input is +waiting, so it can't actually prompt you in a normal way. It +only prints 'Ok.' after you define a word). - When in THIRD, you can see how much space you're currently - using by typing - - here . - - The number THIRD replies is the number of machine words (ints) - that the dictionary (the first code) takes up, plus the - 512 ints for the return stack. If you compile the basic - THIRD system without the help word (strings take up one - int per character in the string!), you should find that - you're using around 1000 ints (plus the return stack). - - Thus THIRD gives you a relatively complete FORTH system in - less than 700 chars of C source + about 1000 ints of - memory--and it's portable too (you could copy over the - THIRD memory dump to another machine, in theory). If the - above numbers seem to you to be mixing apples and oranges - (C source and compiled THIRD code), note that you should - in theory be able to stick the compiled THIRD code into - the C source. + 2 3 + . cr ( add 2 and 3, and print it and a newline.) - Software Construction Company gets credit for rekindling - my interest in FORTH and thus indirectly inspiring me - to write this program. +and THIRD responds + + 5 + +Now try: + + : test 11 1 do i . loop cr ; + test + +and THIRD responds + + 1 2 3 4 5 6 7 8 9 10 + + +When in THIRD, you can see how much space you're currently +using by typing + + here . + +The number THIRD replies is the number of machine words (ints) +that the dictionary (the first code) takes up, plus the +512 ints for the return stack. If you compile the basic +THIRD system without the help word (strings take up one +int per character in the string!), you should find that +you're using around 1000 ints (plus the return stack). + +Thus THIRD gives you a relatively complete FORTH system in +less than 700 chars of C source + about 1000 ints of +memory--and it's portable too (you could copy over the +THIRD memory dump to another machine, in theory). If the +above numbers seem to you to be mixing apples and oranges +(C source and compiled THIRD code), note that you should +in theory be able to stick the compiled THIRD code into +the C source. + +Software Construction Company gets credit for rekindling +my interest in FORTH and thus indirectly inspiring me +to write this program. ## Copyright and CC BY-SA 4.0 License: