force use of pandoc version >= 3.1.12.2
The `bin/pandoc-wrapper.sh` tool will verify that the ssytem has a recent enough version of `pandoc(1)`. We explain why we insist on `pandoc(1)`. version >= 3.1.12.2 in comments where the $PANDOC_MIN_VERSION is set. Added `--wrap=preserve` as a default argument to `pandoc(1)`. While this change will impact every HTML file generated, we believe this will improve the ability of someone to look at the generated HTML and correlate with the original markdown. Changed `bin/pandoc-wrapper.sh` VERSION from "1.4.2 2024-03-17" to "1.4.3 2024-03-18". Performed `make www` to achieve all of the above and to generate HTML using the new `--wrap=preserve` `pandoc(1)` mode.
This commit is contained in:
1 parent
9eb7a54e9f
commit
b0b212acb1
402 files changed
+37061
-55132
No files matched your search
@@ -121,25 +121,22 @@
|
||||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
|
||||
<p><a href="buzzard.2.README.md">buzzard.2.README.md</a> this file<br />
|
||||
<a href="buzzard.2.design.md">buzzard.2.design.md</a> description of
|
||||
FIRST (design documentation of THIRD)<br />
|
||||
<a href="buzzard.2.design.md">buzzard.2.design.md</a> description of FIRST (design documentation of THIRD)<br />
|
||||
<a href="third">third</a> implementation of THIRD in FIRST<br />
|
||||
<a href="help.th">help.th</a> online listing of THIRD primitives<br />
|
||||
</p>
|
||||
<h1 id="first-demos">FIRST demos:</h1>
|
||||
<p>Use <code>./first < <demo></code>.</p>
|
||||
<p><a href="demo1.1st">demo1.1st</a> prints Hello World! assuming
|
||||
ASCII</p>
|
||||
<p><a href="demo1.1st">demo1.1st</a> prints Hello World! assuming ASCII</p>
|
||||
<h1 id="third-demos">THIRD demos:</h1>
|
||||
<p>Use <code>cat third <demo> | ./first</code>.</p>
|
||||
<h2 id="demo-files">Demo files:</h2>
|
||||
<p><a href="demo1.th">demo1.th</a> prints Hello World! regardless of
|
||||
character set <a href="demo2.th">demo2.th</a> demonstrates a simple loop
|
||||
<a href="demo3.th">demo3.th</a> demonstrates a simple if test <a
|
||||
href="demo4.th">demo4.th</a> recursive factorial calculating on the way
|
||||
up <a href="demo5.th">demo5.th</a> recursive factorial calculating on
|
||||
the way down <a href="demo6.th">demo6.th</a> demonstrates switching from
|
||||
compiler to execution mode</p>
|
||||
<p><a href="demo1.th">demo1.th</a> prints Hello World! regardless of character set
|
||||
<a href="demo2.th">demo2.th</a> demonstrates a simple loop
|
||||
<a href="demo3.th">demo3.th</a> demonstrates a simple if test
|
||||
<a href="demo4.th">demo4.th</a> recursive factorial calculating on the way up
|
||||
<a href="demo5.th">demo5.th</a> recursive factorial calculating on the way down
|
||||
<a href="demo6.th">demo6.th</a> demonstrates switching from compiler to execution mode</p>
|
||||
<h1 id="interactive-third">Interactive THIRD:</h1>
|
||||
<p>Use <code>cat third - | ./first</code>.</p>
|
||||
<p>To include the primitive on-line help, use
|
||||
|
||||
@@ -122,62 +122,63 @@
|
||||
|
||||
<h1 id="first-third-almost-forth">FIRST & THIRD (almost FORTH)</h1>
|
||||
<p>FORTH is a language mostly familiar to users of “small” machines.
|
||||
FORTH programs are small because they are interpreted–a function call in
|
||||
FORTH takes two bytes. FORTH is an extendable language– built-in
|
||||
primitives are indistinguishable from user-defined <em>words</em>. FORTH
|
||||
interpreters are small because much of the system can be coded in
|
||||
FORTH–only a small number of primitives need to be implemented. Some
|
||||
FORTH interpreters can also compile defined words into machine code,
|
||||
resulting in a fast system.</p>
|
||||
FORTH programs are small because they are interpreted–a function
|
||||
call in FORTH takes two bytes. FORTH is an extendable language–
|
||||
built-in primitives are indistinguishable from user-defined
|
||||
<em>words</em>. FORTH interpreters are small because much of the system
|
||||
can be coded in FORTH–only a small number of primitives need to
|
||||
be implemented. Some FORTH interpreters can also compile defined
|
||||
words into machine code, resulting in a fast system.</p>
|
||||
<p>FIRST is an incredibly small language which is sufficient for
|
||||
defining the language THIRD, which is mostly like FORTH. There are some
|
||||
differences, and THIRD is probably just enough like FORTH for those
|
||||
differences to be disturbing to regular FORTH users.</p>
|
||||
<p>The only existing FIRST interpreter is written in obfuscated C, and
|
||||
rings in at under 800 bytes of source code, although through deletion of
|
||||
both whitespace and obfuscation it can be brought to about 650
|
||||
defining the language THIRD, which is mostly like FORTH. There are
|
||||
some differences, and THIRD is probably just enough like FORTH for
|
||||
those differences to be disturbing to regular FORTH users.</p>
|
||||
<p>The only existing FIRST interpreter is written in obfuscated C,
|
||||
and rings in at under 800 bytes of source code, although through
|
||||
deletion of both whitespace and obfuscation it can be brought to about 650
|
||||
bytes.</p>
|
||||
<p>This document FIRST defines the FIRST environment and primitives,
|
||||
with relevant design decision explanations. It secondly documents the
|
||||
general strategies we will use to implement THIRD. The THIRD section
|
||||
demonstrates how the complete THIRD system is built up using FIRST.</p>
|
||||
with relevant design decision explanations. It secondly documents
|
||||
the general strategies we will use to implement THIRD. The THIRD
|
||||
section demonstrates how the complete THIRD system is built up
|
||||
using FIRST.</p>
|
||||
<h2 id="section-1-first">Section 1: FIRST</h2>
|
||||
<h3 id="environment">Environment</h3>
|
||||
<p>FIRST implements a virtual machine. The machine has three chunks of
|
||||
memory: “main memory”, “the stack”, and “string storage”. When the
|
||||
virtual machine wishes to do random memory accesses, they come out of
|
||||
main memory–it cannot access the stack or string storage.</p>
|
||||
<p>FIRST implements a virtual machine. The machine has three chunks
|
||||
of memory: “main memory”, “the stack”, and “string storage”. When
|
||||
the virtual machine wishes to do random memory accesses, they come
|
||||
out of main memory–it cannot access the stack or string storage.</p>
|
||||
<p>The stack is simply a standard LIFO data structure that is used
|
||||
implicitly by most of the FIRST primitives. The stack is made up of
|
||||
<code>int</code>s, whatever size they are on the host machine.</p>
|
||||
implicitly by most of the FIRST primitives. The stack is made up
|
||||
of <code>int</code>s, whatever size they are on the host machine.</p>
|
||||
<p>String storage is used to store the names of built-in and defined
|
||||
primitives. Separate storage is used for these because it allows the C
|
||||
code to use C string operations, reducing C source code size.</p>
|
||||
primitives. Separate storage is used for these because it allows
|
||||
the C code to use C string operations, reducing C source code size.</p>
|
||||
<p>Main memory is a large array of <code>int</code>s. When we speak of
|
||||
addresses, we actually mean indices into main memory. Main memory is
|
||||
used for two things, primarily: the return stack and the dictionary.</p>
|
||||
<p>The return stack is a LIFO data structure, independent of the
|
||||
above-mentioned “stack”, which is used by FIRST to keep track of
|
||||
function call return addresses.</p>
|
||||
<p>The dictionary is a list of words. Each word contains a header and a
|
||||
data field. In the header is the address of the previous word, an index
|
||||
into the string storage indicating where the name of this word is
|
||||
stored, and a “code pointer”. The code pointer is simply an integer
|
||||
which names which “machine-language-primitive” implements this
|
||||
instruction. For example, for defined words the code pointer names the
|
||||
“run some code” primitive, which pushes the current program counter onto
|
||||
the return stack and sets the counter to the address of the data field
|
||||
for this word.</p>
|
||||
<p>There are several important pointers into main memory. There is a
|
||||
pointer to the most recently defined word, which is used to start
|
||||
searches back through memory when compiling words. There is a pointer to
|
||||
the top of the return stack. There is a pointer to the current end of
|
||||
the dictionary, used while compiling.</p>
|
||||
<p>For the last two pointers, namely the return stack pointer and the
|
||||
dictionary pointer, there is an important distinction: the pointers
|
||||
themselves are stored in main memory (in <code>FIRST</code>’s main
|
||||
memory). This is critical, because it means FIRST programs can get at
|
||||
them without any further primitives needing to be defined.</p>
|
||||
addresses, we actually mean indices into main memory. Main memory
|
||||
is used for two things, primarily: the return stack and the dictionary.</p>
|
||||
<p>The return stack is a LIFO data structure, independent of
|
||||
the above-mentioned “stack”, which is used by FIRST to keep
|
||||
track of function call return addresses.</p>
|
||||
<p>The dictionary is a list of words. Each word contains a header
|
||||
and a data field. In the header is the address of the previous word,
|
||||
an index into the string storage indicating where the name of this
|
||||
word is stored, and a “code pointer”. The code pointer is simply
|
||||
an integer which names which “machine-language-primitive” implements
|
||||
this instruction. For example, for defined words the code pointer
|
||||
names the “run some code” primitive, which pushes the current program
|
||||
counter onto the return stack and sets the counter to the address of
|
||||
the data field for this word.</p>
|
||||
<p>There are several important pointers into main memory. There is
|
||||
a pointer to the most recently defined word, which is used to start
|
||||
searches back through memory when compiling words. There is a pointer
|
||||
to the top of the return stack. There is a pointer to the current
|
||||
end of the dictionary, used while compiling.</p>
|
||||
<p>For the last two pointers, namely the return stack pointer and
|
||||
the dictionary pointer, there is an important distinction: the pointers
|
||||
themselves are stored in main memory (in <code>FIRST</code>’s main memory). This
|
||||
is critical, because it means FIRST programs can get at them without
|
||||
any further primitives needing to be defined.</p>
|
||||
<h3 id="instructions">Instructions</h3>
|
||||
<p>There are two kinds of FIRST instructions, normal instructions and
|
||||
immediate instructions. Immediate instructions do something significant
|
||||
@@ -196,8 +197,7 @@ means that by default FIRST simply compiles things.</p>
|
||||
<0 less than 0 pop top element of stack, push 1 if < 0 else 0</code></pre>
|
||||
<p>Note that we can synthesize addition and negation from binary minus,
|
||||
but we cannot synthesize a time efficient divide or multiply from it.
|
||||
<code><0</code> is synthesize-able, but only in a non-portable
|
||||
way.</p>
|
||||
<code><0</code> is synthesize-able, but only in a non-portable way.</p>
|
||||
<h4 id="memory-operations">Memory Operations</h4>
|
||||
<pre><code>SYMBOL NAME FUNCTION
|
||||
|
||||
@@ -216,16 +216,14 @@ _read read a space-delimited word, find it in the
|
||||
dictionary, and compile a pointer to
|
||||
that word's code pointer onto the
|
||||
current end of the dictionary</code></pre>
|
||||
<p>Although <code>_read</code> could be synthesized from key, we need
|
||||
<code>_read</code> to be able to compile words to be able to start any
|
||||
syntheses.</p>
|
||||
<p>Although <code>_read</code> could be synthesized from key, we need <code>_read</code> to be able
|
||||
to compile words to be able to start any syntheses.</p>
|
||||
<h4 id="execution-operations">Execution Operations</h4>
|
||||
<pre><code>NAME FUNCTION
|
||||
|
||||
exit leave the current function: pop the return stack
|
||||
into the program counter</code></pre>
|
||||
<h4 id="immediate-compilation-operations">Immediate (compilation)
|
||||
Operations</h4>
|
||||
<h4 id="immediate-compilation-operations">Immediate (compilation) Operations</h4>
|
||||
<pre><code>SYMBOL NAME FUNCTION
|
||||
|
||||
: define read in the next space-delimited word, add it to
|
||||
@@ -237,32 +235,31 @@ Operations</h4>
|
||||
immediate immediate when used immediately after a name following a ':',
|
||||
it makes the word being defined run whenever
|
||||
it is typed.</code></pre>
|
||||
<p><code>:</code> cannot be synthesized, because we could not synthesize
|
||||
anything. <code>immediate</code> has to be an immediate operation, so it
|
||||
could not be synthesized unless by default operations were immediate;
|
||||
but that would preclude our being able to do any useful compilation.</p>
|
||||
<p><code>:</code> cannot be synthesized, because we could not synthesize anything.
|
||||
<code>immediate</code> has to be an immediate operation, so it could not be
|
||||
synthesized unless by default operations were immediate; but that
|
||||
would preclude our being able to do any useful compilation.</p>
|
||||
<h4 id="stack-operations">Stack Operations</h4>
|
||||
<pre><code>NAME FUNCTION
|
||||
|
||||
pick pop top of stack, use as index into stack and copy up
|
||||
that element</code></pre>
|
||||
<p>If the data stack were stored in main memory, we could synthesize
|
||||
<code>pick</code>; but putting the stack and stack pointer in main
|
||||
memory would significantly increase the C source code size.</p>
|
||||
<p>There are three more primitives, but they are “internal only”– they
|
||||
have no names and no dictionary entries. The first is
|
||||
<code>pushint</code>. It takes the next integer out of the instruction
|
||||
stream and pushes it on the stack. This could be synthesized, but
|
||||
probably not without using integer constants. It is generated by
|
||||
<code>_read</code> when the input is not a known word. The second is
|
||||
<code>compile me</code>. When this instruction is executed, a pointer to
|
||||
the word’s data field is appended to the dictionary. The third is
|
||||
<code>run me</code>–the word’s data field is taken to be a stream of
|
||||
pointers to words, and is executed.</p>
|
||||
<p>One last note about the environment: FIRST builds a very small word
|
||||
internally that it executes as its main loop. This word calls
|
||||
<code>_read</code> and then calls itself. Each time it calls itself, it
|
||||
uses up a word on the return stack, so it will eventually trash things.
|
||||
<p>If the data stack were stored in main memory, we could synthesize <code>pick</code>;
|
||||
but putting the stack and stack pointer in main memory would significantly
|
||||
increase the C source code size.</p>
|
||||
<p>There are three more primitives, but they are “internal only”–
|
||||
they have no names and no dictionary entries. The first is
|
||||
<code>pushint</code>. It takes the next integer out of the instruction stream
|
||||
and pushes it on the stack. This could be synthesized, but probably
|
||||
not without using integer constants. It is generated by <code>_read</code> when
|
||||
the input is not a known word. The second is <code>compile me</code>. When
|
||||
this instruction is executed, a pointer to the word’s data field is
|
||||
appended to the dictionary. The third is <code>run me</code>–the word’s data
|
||||
field is taken to be a stream of pointers to words, and is executed.</p>
|
||||
<p>One last note about the environment: FIRST builds a very small
|
||||
word internally that it executes as its main loop. This word calls
|
||||
<code>_read</code> and then calls itself. Each time it calls itself, it uses
|
||||
up a word on the return stack, so it will eventually trash things.
|
||||
This is discussed some more in section 2.</p>
|
||||
<p>Here’s a handy summary of all the FIRST words:</p>
|
||||
<pre><code>WORD DESCRIPTION
|
||||
@@ -275,18 +272,18 @@ _read read a word from input and compile a pointer to it
|
||||
exit stop running the current function
|
||||
: compile the header of a definition
|
||||
immediate modify the header to create an immediate word</code></pre>
|
||||
<p>Here is a sample FIRST program. I’m assuming you’re using the ASCII
|
||||
character set. FIRST does not depend upon ASCII, but since FIRST has no
|
||||
syntax for character constants, one normally has to use decimal values.
|
||||
This can be avoided using <code>getchar(3)</code>, though. Oh. One other
|
||||
odd thing. FIRST initially builds its symbol table by calling
|
||||
<code>:</code> several times, so it needs to get the names of the base
|
||||
<p>Here is a sample FIRST program. I’m assuming you’re using
|
||||
the ASCII character set. FIRST does not depend upon ASCII, but
|
||||
since FIRST has no syntax for character constants, one normally has
|
||||
to use decimal values. This can be avoided using <code>getchar(3)</code>, though.
|
||||
Oh. One other odd thing. FIRST initially builds its symbol table
|
||||
by calling <code>:</code> several times, so it needs to get the names of the base
|
||||
symbols as its first 13 words of input. You could even name them
|
||||
differently if you wanted.</p>
|
||||
<p>These FIRST programs have FORTH comments in them: they are contained
|
||||
inside parentheses. FIRST programs cannot have FORTH comments; but I
|
||||
need some device to indicate what’s going on. (THIRD programs are an
|
||||
entirely different subject.)</p>
|
||||
inside parentheses. FIRST programs cannot have FORTH comments; but I need
|
||||
some device to indicate what’s going on. (THIRD programs are an entirely
|
||||
different subject.)</p>
|
||||
<pre><code> ( Our first line gives the symbols for the built-ins )
|
||||
: immediate _read @ ! - * / <0 exit echo key _pick
|
||||
|
||||
@@ -315,73 +312,68 @@ test
|
||||
Hello
|
||||
)</code></pre>
|
||||
<h2 id="section-2-motivating-third">Section 2: Motivating THIRD</h2>
|
||||
<p>What is missing from FIRST? There are a large number of important
|
||||
primitives that aren’t implemented, but which are easy to implement.
|
||||
<code>drop</code>, which throws away the top of the stack, can be
|
||||
implemented as <code>{ 0 * + }</code> – that is, multiply the top of the
|
||||
stack by <code>0</code> (which turns the top of the stack into a
|
||||
<code>0</code>), and then add the top two elements of the stack.</p>
|
||||
<p>What is missing from FIRST? There are a large number of
|
||||
important primitives that aren’t implemented, but which are
|
||||
easy to implement. <code>drop</code>, which throws away the top of the
|
||||
stack, can be implemented as <code>{ 0 * + }</code> – that is, multiply
|
||||
the top of the stack by <code>0</code> (which turns the top of the stack
|
||||
into a <code>0</code>), and then add the top two elements of the stack.</p>
|
||||
<p><code>dup</code>, which copies the top of the stack, can be easily
|
||||
implemented using temporary storage locations. Conveniently, FIRST
|
||||
leaves memory locations <code>3</code>, <code>4</code>, and
|
||||
<code>5</code> unused. So we can implement <code>dup</code> by writing
|
||||
the top of stack into <code>3</code>, and then reading it out twice:
|
||||
<code>{ 3 ! 3 @ 3 @ }</code>.</p>
|
||||
<p>We will never use the FIRST primitive <code>pick</code> in building
|
||||
THIRD, just to show that it can be done; <code>pick</code> is only
|
||||
provided because <code>pick</code> itself cannot be built out of the
|
||||
rest of <code>FIRST</code>’s building blocks.</p>
|
||||
<p>So, instead of worrying about stack primitives and the like, what
|
||||
else is missing from FIRST? We get recursion, but no control flow–no
|
||||
conditional operations. We cannot at the moment write a looping routine
|
||||
which terminates.</p>
|
||||
<p>Another glaring dissimilarity between FIRST and FORTH is that there
|
||||
is no “command mode”–you cannot be outside of a <code>:</code>
|
||||
definition and issue some straight commands to be executed. Also, as we
|
||||
noted above, we cannot do comments.</p>
|
||||
<p>FORTH also provides a system for defining new data types, using the
|
||||
words (in one version of FORTH) <code>builds and does</code>. We would
|
||||
like to implement these words as well.</p>
|
||||
<p>As the highest priority thing, we will build control flow structures
|
||||
first. Once we have control structures, we can write recursive routines
|
||||
that terminate, and we are ready to tackle tasks like parsing, and the
|
||||
building of a command mode.</p>
|
||||
<p>By the way, location <code>0</code> holds the dictionary pointer,
|
||||
location <code>1</code> holds the return stack pointer, and location
|
||||
<code>2</code> should always be <code>0</code>–it’s a fake dictionary
|
||||
entry that means <code>pushint</code>.</p>
|
||||
implemented using temporary storage locations. Conveniently,
|
||||
FIRST leaves memory locations <code>3</code>, <code>4</code>, and <code>5</code> unused. So we can
|
||||
implement <code>dup</code> by writing the top of stack into <code>3</code>, and then
|
||||
reading it out twice: <code>{ 3 ! 3 @ 3 @ }</code>.</p>
|
||||
<p>We will never use the FIRST primitive <code>pick</code> in building THIRD,
|
||||
just to show that it can be done; <code>pick</code> is only provided because
|
||||
<code>pick</code> itself cannot be built out of the rest of <code>FIRST</code>’s building
|
||||
blocks.</p>
|
||||
<p>So, instead of worrying about stack primitives and the
|
||||
like, what else is missing from FIRST? We get recursion, but
|
||||
no control flow–no conditional operations. We cannot at the
|
||||
moment write a looping routine which terminates.</p>
|
||||
<p>Another glaring dissimilarity between FIRST and FORTH is
|
||||
that there is no “command mode”–you cannot be outside of a
|
||||
<code>:</code> definition and issue some straight commands to be executed.
|
||||
Also, as we noted above, we cannot do comments.</p>
|
||||
<p>FORTH also provides a system for defining new data types,
|
||||
using the words (in one version of FORTH) <code>builds and does</code>.
|
||||
We would like to implement these words as well.</p>
|
||||
<p>As the highest priority thing, we will build control flow
|
||||
structures first. Once we have control structures, we can
|
||||
write recursive routines that terminate, and we are ready to
|
||||
tackle tasks like parsing, and the building of a command mode.</p>
|
||||
<p>By the way, location <code>0</code> holds the dictionary pointer, location
|
||||
<code>1</code> holds the return stack pointer, and location <code>2</code> should always
|
||||
be <code>0</code>–it’s a fake dictionary entry that means <code>pushint</code>.</p>
|
||||
<h2 id="section-3-building-third">Section 3: Building THIRD</h2>
|
||||
<p>In this section we’ll eventually have real comments.</p>
|
||||
<p>The first thing we have to do is give the symbols for our
|
||||
built-ins.</p>
|
||||
<p>The first thing we have to do is give the symbols for our built-ins.</p>
|
||||
<pre><code>: immediate _read @ ! - * / < exit echo key _pick</code></pre>
|
||||
<p>Next we want to be mildly self commenting, so we define the word
|
||||
<code>r</code> to push the <em>address of the return stack pointer</em>
|
||||
onto the stack–NOT the value of the return stack pointer. (In fact, when
|
||||
we run <code>r</code>, the value of the return stack pointer is
|
||||
temporarily changed.)</p>
|
||||
<p>Next we want to be mildly self commenting, so we define the word <code>r</code> to push
|
||||
the <em>address of the return stack pointer</em> onto the stack–NOT the value of the
|
||||
return stack pointer. (In fact, when we run <code>r</code>, the value of the return stack
|
||||
pointer is temporarily changed.)</p>
|
||||
<pre><code>: r 1 exit</code></pre>
|
||||
<p>Next, we’re currently executing a short loop that contains
|
||||
<code>_read</code> and recursion, which is slowly blowing up the return
|
||||
stack. So let’s define a new word, from which you can never return. What
|
||||
it does is drops the top value off the return stack, calls
|
||||
<code>_read</code>, then calls itself. Because it kills the top of the
|
||||
return stack, it can recurse indefinitely.</p>
|
||||
<p>Next, we’re currently executing a short loop that contains <code>_read</code> and
|
||||
recursion, which is slowly blowing up the return stack. So let’s define a new
|
||||
word, from which you can never return. What it does is drops the top value off
|
||||
the return stack, calls <code>_read</code>, then calls itself. Because it kills the top of
|
||||
the return stack, it can recurse indefinitely.</p>
|
||||
<pre><code>: ]
|
||||
r @ Get the value of the return stack pointer
|
||||
1 - Subtract one
|
||||
r ! Store it back into the return stack pointer
|
||||
_read Read and compile one word
|
||||
] Start over</code></pre>
|
||||
<p>Notice that we don’t need to exit, since we never come back. Also,
|
||||
it’s possible that an immediate word may get run during
|
||||
<code>_read</code>, and that <code>_read</code> will never return!</p>
|
||||
<p>Notice that we don’t need to exit, since we never come back. Also, it’s
|
||||
possible that an immediate word may get run during <code>_read</code>, and that <code>_read</code>
|
||||
will never return!</p>
|
||||
<p>Now let’s get compile running.</p>
|
||||
<pre><code>: main immediate ]
|
||||
main</code></pre>
|
||||
<p>Next off, I’m going to do this the easy but non-portable way, and put
|
||||
some character constant definitions in. I wanted them at the top of the
|
||||
file, but that would have burned too much of the return stack.</p>
|
||||
<p>Next off, I’m going to do this the easy but non-portable way, and put some
|
||||
character constant definitions in. I wanted them at the top of the file, but
|
||||
that would have burned too much of the return stack.</p>
|
||||
<pre><code>: '"' 34 exit
|
||||
: ')' 41 exit
|
||||
: '\n' 10 exit
|
||||
@@ -390,29 +382,28 @@ file, but that would have burned too much of the return stack.</p>
|
||||
: '-' 45 exit
|
||||
|
||||
: cr '\n' echo exit</code></pre>
|
||||
<p>Next, we want to define some temporary variables for locations
|
||||
<code>3</code>, <code>4</code>, and <code>5</code>, since this’ll make
|
||||
our code look clearer.</p>
|
||||
<p>Next, we want to define some temporary variables for locations <code>3</code>, <code>4</code>, and
|
||||
<code>5</code>, since this’ll make our code look clearer.</p>
|
||||
<pre><code>: _x 3 @ exit
|
||||
: _x! 3 ! exit
|
||||
: _y 4 @ exit
|
||||
: _y! 4 ! exit
|
||||
</code></pre>
|
||||
<p>OK. Now, we want to make THIRD look vaguely like FORTH, so we’re
|
||||
going to define <code>;</code>. What <code>;</code> ought to do is
|
||||
terminate a compilation, and turn control over to the command-mode
|
||||
handler. We don’t have one, so all we want <code>;</code> to do for now
|
||||
is compile <code>exit</code> at the end of the current word. To do this
|
||||
we’ll need several other words.</p>
|
||||
<p>Swap by writing out the top two elements into temps, and then reading
|
||||
them back in the other order.</p>
|
||||
<p>OK. Now, we want to make THIRD look vaguely like FORTH,
|
||||
so we’re going to define <code>;</code>. What <code>;</code> ought to do is
|
||||
terminate a compilation, and turn control over to the
|
||||
command-mode handler. We don’t have one, so all we want
|
||||
<code>;</code> to do for now is compile <code>exit</code> at the end of the
|
||||
current word. To do this we’ll need several other words.</p>
|
||||
<p>Swap by writing out the top two elements into temps, and
|
||||
then reading them back in the other order.</p>
|
||||
<pre><code>: swap _x! _y! _x _y exit</code></pre>
|
||||
<p>Take another look and make sure you see why that works, since it
|
||||
LOOKS like I’m reading them back in the same order–in fact, it not only
|
||||
looks like it, but I AM!</p>
|
||||
<p>Addition might be nice to have. To add, we need to negate the top
|
||||
element of the stack, and then subtract. To negate, we subtract from
|
||||
<code>0</code>.</p>
|
||||
<p>Take another look and make sure you see why that works,
|
||||
since it LOOKS like I’m reading them back in the same
|
||||
order–in fact, it not only looks like it, but I AM!</p>
|
||||
<p>Addition might be nice to have. To add, we need to
|
||||
negate the top element of the stack, and then subtract.
|
||||
To negate, we subtract from <code>0</code>.</p>
|
||||
<pre><code>: +
|
||||
0 swap -
|
||||
-
|
||||
@@ -420,12 +411,13 @@ element of the stack, and then subtract. To negate, we subtract from
|
||||
</code></pre>
|
||||
<p>Create a copy of the top of stack.</p>
|
||||
<pre><code>: dup _x! _x _x exit</code></pre>
|
||||
<p>Get a mnemonic name for our dictionary pointer–we need to compile
|
||||
stuff, so it goes through this.</p>
|
||||
<p>Get a mnemonic name for our dictionary pointer–we need
|
||||
to compile stuff, so it goes through this.</p>
|
||||
<pre><code>: h 0 exit</code></pre>
|
||||
<p>We’re going to need to advance that pointer, so let’s make a generic
|
||||
pointer-advancing function. Given a pointer to a memory location,
|
||||
increment the value at that memory location.</p>
|
||||
<p>We’re going to need to advance that pointer, so let’s
|
||||
make a generic pointer-advancing function.
|
||||
Given a pointer to a memory location, increment the value
|
||||
at that memory location.</p>
|
||||
<pre><code>: inc
|
||||
dup @ Get another copy of the address, and get the value
|
||||
so now we have value, address on top of stack.
|
||||
@@ -441,12 +433,13 @@ stack into the dictionary, and advance the pointer</p>
|
||||
h inc And increment the dictionary pointer
|
||||
exit</code></pre>
|
||||
<p><code>'</code> is a standard FORTH word. It should push the address
|
||||
of the word that follows it onto the stack. We could do this by making
|
||||
<code>'</code> immediate, but then it’d need to parse the next word.
|
||||
Instead, we compile the next word as normal. When <code>'</code> is
|
||||
executed, the top of the return stack will point into the instruction
|
||||
stream immediately after the <code>'</code>. We push the word there, and
|
||||
advance the return stack pointer so that we don’t execute it.</p>
|
||||
of the word that follows it onto the stack. We could
|
||||
do this by making <code>'</code> immediate, but then it’d need to
|
||||
parse the next word. Instead, we compile the next word
|
||||
as normal. When <code>'</code> is executed, the top of the return
|
||||
stack will point into the instruction stream immediately
|
||||
after the <code>'</code>. We push the word there, and advance the
|
||||
return stack pointer so that we don’t execute it.</p>
|
||||
<pre><code>: '
|
||||
r @ Get the address of the top of return stack
|
||||
We currently have a pointer to the top of return stack
|
||||
@@ -469,18 +462,19 @@ the address of <code>exit</code> onto the stack, then writes it out.</p>
|
||||
exit And we should return</code></pre>
|
||||
<p>Now let’s test out <code>;</code> by defining a useful word:</p>
|
||||
<pre><code>: drop 0 * + ;</code></pre>
|
||||
<p>Since we have <code>inc</code>, we ought to make
|
||||
<code>dec</code>:</p>
|
||||
<p>Since we have <code>inc</code>, we ought to make <code>dec</code>:</p>
|
||||
<pre><code>: dec dup @ 1 - swap ! ;</code></pre>
|
||||
<p>Our next goal, now that we have <code>;</code>, is to implement
|
||||
<code>if-then</code>. To do this, we’ll need to play fast and loose with
|
||||
the return stack, so let’s make some words to save us some effort.</p>
|
||||
<p>First we want a word that pops off the top of the normal stack and
|
||||
pushes it on top of the return stack. We’ll call this <code>tor</code>,
|
||||
for TO-Return-stack. It sounds easy, but when <code>tor</code> is
|
||||
running, there’s an extra value on the return stack–<code>tor</code>’s
|
||||
return address! So we have to pop that off first… We better just bite
|
||||
the bullet and code it out–but we can’t really break it into smaller
|
||||
<code>if-then</code>. To do this, we’ll need to play fast and
|
||||
loose with the return stack, so let’s make some
|
||||
words to save us some effort.</p>
|
||||
<p>First we want a word that pops off the top of the normal
|
||||
stack and pushes it on top of the return stack. We’ll
|
||||
call this <code>tor</code>, for TO-Return-stack. It sounds easy,
|
||||
but when <code>tor</code> is running, there’s an extra value on the
|
||||
return stack–<code>tor</code>’s return address! So we have to pop
|
||||
that off first… We better just bite the bullet and
|
||||
code it out–but we can’t really break it into smaller
|
||||
words, because that’ll trash the return stack.</p>
|
||||
<pre><code>: tor
|
||||
r @ @ Get the value off the top of the return stack
|
||||
@@ -489,8 +483,8 @@ words, because that’ll trash the return stack.</p>
|
||||
r @ 1 + r ! Increment the return stack pointer--but can't use inc
|
||||
r @ ! Store our return address back on the return stack
|
||||
;</code></pre>
|
||||
<p>Next we want the opposite routine, which pops the top of the return
|
||||
stack, and puts it on the normal stack.</p>
|
||||
<p>Next we want the opposite routine, which pops the top
|
||||
of the return stack, and puts it on the normal stack.</p>
|
||||
<pre><code>: fromr
|
||||
r @ @ Save old value
|
||||
r @ 1 - r ! Decrement pointer
|
||||
@@ -498,25 +492,26 @@ stack, and puts it on the normal stack.</p>
|
||||
swap Bring return address to top
|
||||
r @ ! Store it and return
|
||||
;</code></pre>
|
||||
<p>Now, if we have a routine that’s recursing, and we want to be polite
|
||||
about the return stack, right before we recurse we can run
|
||||
<code>{ fromr drop }</code> so the stack won’t blow up. This means,
|
||||
though, that the first time we enter this recursive routine, we blow our
|
||||
<em>real</em> return address–so when we’re done, we’ll return up two
|
||||
levels. To save a little, we make <code>tail</code> mean
|
||||
<code>{ fromr drop }</code>; however, it’s more complex since there’s a
|
||||
new value on top of the return stack.</p>
|
||||
<p>Now, if we have a routine that’s recursing, and we
|
||||
want to be polite about the return stack, right before
|
||||
we recurse we can run <code>{ fromr drop }</code> so the stack won’t
|
||||
blow up. This means, though, that the first time we
|
||||
enter this recursive routine, we blow our <em>real</em> return
|
||||
address–so when we’re done, we’ll return up two levels.
|
||||
To save a little, we make <code>tail</code> mean <code>{ fromr drop }</code>;
|
||||
however, it’s more complex since there’s a new value on
|
||||
top of the return stack.</p>
|
||||
<pre><code>: tail fromr fromr drop tor ;</code></pre>
|
||||
<p>Now, we want to do <code>if</code>. To do this, we need to convert
|
||||
values to boolean values. The next few words set this up.</p>
|
||||
values to boolean values. The next few words set this
|
||||
up.</p>
|
||||
<p><code>minus</code> gives us unary negation.</p>
|
||||
<pre><code>: minus 0 swap - ;</code></pre>
|
||||
<p>If top of stack is boolean, <code>bnot</code> gives us inverse</p>
|
||||
<pre><code>: bnot 1 swap - ;</code></pre>
|
||||
<p>To compare two numbers, subtract and compare to <code>0</code>.</p>
|
||||
<pre><code>: < - <0 ;</code></pre>
|
||||
<p><code>logical</code> turns the top of stack into either
|
||||
<code>0</code> or <code>1</code>.</p>
|
||||
<p><code>logical</code> turns the top of stack into either <code>0</code> or <code>1</code>.</p>
|
||||
<pre><code>: logical
|
||||
dup Get two copies of it
|
||||
0 < 1 if < 0, 0 otherwise
|
||||
@@ -526,14 +521,13 @@ values to boolean values. The next few words set this up.</p>
|
||||
;</code></pre>
|
||||
<p><code>not</code> returns 1 if top of stack is 0, and 0 otherwise</p>
|
||||
<pre><code>: not logical bnot ;</code></pre>
|
||||
<p>We can test equality by subtracting and comparing to
|
||||
<code>0</code>.</p>
|
||||
<p>We can test equality by subtracting and comparing to <code>0</code>.</p>
|
||||
<pre><code>: = - not ;</code></pre>
|
||||
<p>Just to show how you compute a branch: Suppose you’ve compiled a call
|
||||
to branch, and immediately after it is an integer constant with the
|
||||
offset of how far to branch. To branch, we use the return stack to read
|
||||
the offset, and add that on to the top of the return stack, and
|
||||
return.</p>
|
||||
<p>Just to show how you compute a branch: Suppose you’ve
|
||||
compiled a call to branch, and immediately after it is
|
||||
an integer constant with the offset of how far to branch.
|
||||
To branch, we use the return stack to read the offset, and
|
||||
add that on to the top of the return stack, and return.</p>
|
||||
<pre><code>: branch
|
||||
r @ Address of top of return stack
|
||||
@ Our return address
|
||||
@@ -542,12 +536,12 @@ return.</p>
|
||||
+ The address we want to execute at
|
||||
r @ ! Store it back onto the return stack
|
||||
;</code></pre>
|
||||
<p>For conditional branches, we want to branch by a certain amount if
|
||||
true, otherwise we want to skip over the branch offset constant–that is,
|
||||
branch by one. Assuming that the top of the stack is the branch offset,
|
||||
and the second on the stack is <code>1</code> if we should branch, and
|
||||
<code>0</code> if not, the following computes the correct branch
|
||||
offset.</p>
|
||||
<p>For conditional branches, we want to branch by a certain
|
||||
amount if true, otherwise we want to skip over the branch
|
||||
offset constant–that is, branch by one. Assuming that
|
||||
the top of the stack is the branch offset, and the second
|
||||
on the stack is <code>1</code> if we should branch, and <code>0</code> if not, the
|
||||
following computes the correct branch offset.</p>
|
||||
<pre><code>: computebranch 1 - * 1 + ;</code></pre>
|
||||
<p>Branch if the value on top of the stack is <code>0</code>.</p>
|
||||
<pre><code>: notbranch
|
||||
@@ -558,31 +552,31 @@ offset.</p>
|
||||
r @ ! Store it
|
||||
;</code></pre>
|
||||
<p><code>here</code> is a standard FORTH word which returns a pointer to
|
||||
the current dictionary address–that is, the value of the dictionary
|
||||
pointer.</p>
|
||||
the current dictionary address–that is, the value of
|
||||
the dictionary pointer.</p>
|
||||
<pre><code>: here h @ ;</code></pre>
|
||||
<p>We’re ALL SET to compile <code>if...else...then</code> constructs!
|
||||
Here’s what we do. When we get <code>if</code>, we compile a call to
|
||||
<code>notbranch</code>, and then compile a dummy offset, because we
|
||||
don’t know where the <code>then</code> will be. On the <em>stack</em> we
|
||||
leave the address where we compiled the dummy offset. <code>then</code>
|
||||
will calculate the offset and fill it in for us.</p>
|
||||
Here’s what we do. When we get <code>if</code>, we compile a call
|
||||
to <code>notbranch</code>, and then compile a dummy offset, because
|
||||
we don’t know where the <code>then</code> will be. On the <em>stack</em>
|
||||
we leave the address where we compiled the dummy offset.
|
||||
<code>then</code> will calculate the offset and fill it in for us.</p>
|
||||
<pre><code>: if immediate
|
||||
' notbranch , Compile notbranch
|
||||
here Save the current dictionary address
|
||||
0 , Compile a dummy value
|
||||
;</code></pre>
|
||||
<p><code>then</code> expects the address to <code>fixup</code> to be on
|
||||
the stack.</p>
|
||||
<p><code>then</code> expects the address to <code>fixup</code> to be on the stack.</p>
|
||||
<pre><code>: then immediate
|
||||
dup Make another copy of the address
|
||||
here Find the current location, where to branch to
|
||||
swap - Calculate the difference between them
|
||||
swap ! Bring the address to the top, and store it.
|
||||
;</code></pre>
|
||||
<p>Now that we can do <code>if...then</code> statements, we can do some
|
||||
parsing! Let’s introduce real FORTH comments. <code>find-)</code> will
|
||||
scan the input until it finds a <code>)</code>, and exit.</p>
|
||||
<p>Now that we can do <code>if...then</code> statements, we can do
|
||||
some parsing! Let’s introduce real FORTH comments.
|
||||
<code>find-)</code> will scan the input until it finds a <code>)</code>, and
|
||||
exit.</p>
|
||||
<pre><code>: find-)
|
||||
key Read in a character
|
||||
')' = Compare it to close parentheses
|
||||
|
||||
+155
-225
@@ -130,8 +130,8 @@
|
||||
<h2 id="author"><a name="author"></a>Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Sean_Barrett">Sean Barrett</a><br>
|
||||
Location: <a href="../../location.html#ZZ">ZZ</a> - <em>Unknown
|
||||
location</em> <br><br></li>
|
||||
Location: <a href="../../location.html#ZZ">ZZ</a> - <em>Unknown location</em>
|
||||
<br><br></li>
|
||||
</ul>
|
||||
|
||||
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
|
||||
@@ -141,11 +141,11 @@ location</em> <br><br></li>
|
||||
|
||||
<h2 id="to-build">To build:</h2>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> all</span></code></pre></div>
|
||||
<p>There is an alternate version of this program. See <a
|
||||
href="#alternate-code">Alternate code</a> below for details.</p>
|
||||
<p>There is an alternate version of this program. See <a href="#alternate-code">Alternate
|
||||
code</a> below for details.</p>
|
||||
<h2 id="to-use">To use:</h2>
|
||||
<p>First, you must make sure that <code>first</code> is made first (even
|
||||
though <code>make all</code> should make first first :-) ):</p>
|
||||
<p>First, you must make sure that <code>first</code> is made first (even though <code>make all</code>
|
||||
should make first first :-) ):</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> first</span></code></pre></div>
|
||||
<p>Second:</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co"># get help:</span></span>
|
||||
@@ -163,147 +163,126 @@ though <code>make all</code> should make first first :-) ):</p>
|
||||
<h2 id="try">Try:</h2>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
|
||||
<h2 id="alternate-code">Alternate code:</h2>
|
||||
<p>This alternate version, <a
|
||||
href="buzzard.2.alt.c">buzzard.2.alt.c</a>, does not contain a fix that
|
||||
the author notes in their remarks.</p>
|
||||
<p>This alternate version, <a href="buzzard.2.alt.c">buzzard.2.alt.c</a>, does not contain a
|
||||
fix that the author notes in their remarks.</p>
|
||||
<h3 id="alternate-build">Alternate build:</h3>
|
||||
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> alt</span></code></pre></div>
|
||||
<h3 id="alternate-use">Alternate use:</h3>
|
||||
<p>Use <code>buzzard.2.alt</code> as you would <code>buzzard.2</code>
|
||||
above.</p>
|
||||
<p>Use <code>buzzard.2.alt</code> as you would <code>buzzard.2</code> above.</p>
|
||||
<h3 id="alternate-try">Alternate try:</h3>
|
||||
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.alt.sh</span></span></code></pre></div>
|
||||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||||
<p>Have fun!</p>
|
||||
<h2 id="authors-remarks">Author’s remarks:</h2>
|
||||
<h3 id="what-it-does">What it does</h3>
|
||||
<p><code>first</code> 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’.)</p>
|
||||
<p>It is very difficult to accomplish anything with this set of
|
||||
primitives, but they do have an interesting property.</p>
|
||||
<p>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.</p>
|
||||
<p><code>first</code> 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’.)</p>
|
||||
<p>It is very difficult to accomplish anything with this set
|
||||
of primitives, but they do have an interesting property.</p>
|
||||
<p>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.</p>
|
||||
<h3 id="how-to-run-it">How to run it</h3>
|
||||
<p><code>first</code> 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 <code>first</code>
|
||||
input. Valid <code>first</code> input is defined as any sequence of
|
||||
whitespace-delimited tokens which consist of primitives, new words
|
||||
you’ve defined, and integers (as parsed by <code>"%d"</code>). Invalid
|
||||
input behaves unpredictably, but gives no warning messages. A sample
|
||||
program, <code>demo1.1st</code>, is included, but it only works on ASCII
|
||||
systems.</p>
|
||||
<p>Do not expect to be able to do anything interesting with
|
||||
<code>first</code>.</p>
|
||||
<p>To do something interesting, you need to feed <code>first</code> the
|
||||
file <a href="third">third</a> first. In unix, you can do</p>
|
||||
<div class="sourceCode" id="cb10"><pre
|
||||
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">cat</span> third help.th <span class="at">-</span> <span class="kw">|</span> <span class="ex">./first</span></span></code></pre></div>
|
||||
<p>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); <code>THIRD</code> will prompt
|
||||
you when it is finished. The file <a href="third">third</a> has not been
|
||||
obfuscated, due to sheer kindness on the author’s part.</p>
|
||||
<p>For more information on what you can do once you’ve piped <a
|
||||
href="third">third</a> into first, type <code>help</code> and consult <a
|
||||
href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a>
|
||||
manuals for further reference. Six sample THIRD programs are included in
|
||||
the files <code>demo1.th</code> through <code>demo6.th</code>. See <a
|
||||
href="buzzard.2.README.html">buzzard.2.README.html</a> for more
|
||||
information.</p>
|
||||
<p>Keep in mind that you are still running <code>first</code>, and are
|
||||
for the most part limited by <code>first</code>’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 <code>first</code> and <code>third</code> a second time–I did not
|
||||
care to tackle this project.</p>
|
||||
<p><code>first</code> 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 <code>first</code> input.
|
||||
Valid <code>first</code> input is defined as any sequence of whitespace-delimited
|
||||
tokens which consist of primitives, new words you’ve defined, and
|
||||
integers (as parsed by <code>"%d"</code>). Invalid input behaves unpredictably,
|
||||
but gives no warning messages. A sample program, <code>demo1.1st</code>, is
|
||||
included, but it only works on ASCII systems.</p>
|
||||
<p>Do not expect to be able to do anything interesting with <code>first</code>.</p>
|
||||
<p>To do something interesting, you need to feed <code>first</code> the file
|
||||
<a href="third">third</a> first. In unix, you can do</p>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">cat</span> third help.th <span class="at">-</span> <span class="kw">|</span> <span class="ex">./first</span></span></code></pre></div>
|
||||
<p>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); <code>THIRD</code> will prompt you when it is finished. The file
|
||||
<a href="third">third</a> has not been obfuscated, due to sheer kindness on the author’s
|
||||
part.</p>
|
||||
<p>For more information on what you can do once you’ve piped <a href="third">third</a> into
|
||||
first, type <code>help</code> and consult
|
||||
<a href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a> manuals for
|
||||
further reference. Six sample THIRD programs are included in the files
|
||||
<code>demo1.th</code> through <code>demo6.th</code>. See <a href="buzzard.2.README.html">buzzard.2.README.html</a>
|
||||
for more information.</p>
|
||||
<p>Keep in mind that you are still running <code>first</code>, and are for the most part
|
||||
limited by <code>first</code>’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 <code>first</code> and <code>third</code> a second time–I did not care to
|
||||
tackle this project.</p>
|
||||
<h3 id="compiling">Compiling</h3>
|
||||
<p><code>first</code> is reasonably portable. You may need to adjust the
|
||||
size of the buffers on smaller machines; <code>m[]</code> needs to be at
|
||||
least 2000 long, though.</p>
|
||||
<p>I say <code>first</code> is portable mainly because it uses native
|
||||
types. Unlike
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language),
|
||||
which traditionally allows byte and multi-byte operations, all
|
||||
operations are performed on C <code>int</code>s. That means
|
||||
<code>first</code> code is only as portable as the same code would be in
|
||||
C. As in C, the result of dividing <code>-1</code> by <code>2</code> is
|
||||
machine (or rather compiler) dependent.</p>
|
||||
<p><code>first</code> is reasonably portable. You may need to adjust the size of the buffers
|
||||
on smaller machines; <code>m[]</code> needs to be at least 2000 long, though.</p>
|
||||
<p>I say <code>first</code> is portable mainly because it uses native types. Unlike
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language), which
|
||||
traditionally allows byte and multi-byte operations, all operations are
|
||||
performed on C <code>int</code>s. That means <code>first</code> code is only as portable as the same
|
||||
code would be in C. As in C, the result of dividing <code>-1</code> by <code>2</code> is machine (or
|
||||
rather compiler) dependent.</p>
|
||||
<h3 id="how-is-first-obfuscated">How is first obfuscated?</h3>
|
||||
<p><code>first</code> is obfuscated in several ways. Some minor
|
||||
obfuscations like <code>&w[&m[1]][s]</code> for
|
||||
<code>s+m[w+1]</code> were in the original source but are no longer
|
||||
because, apparently, ANSI doesn’t allow it
|
||||
(<code>gcc -ansi -pedantic</code> doesn’t mind it, though.)</p>
|
||||
<p>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 <code>register</code> allocate
|
||||
it.)</p>
|
||||
<p>More significant are the design obfuscations. <code>m[0]</code> is
|
||||
the “dictionary pointer”, used when compiling words, and
|
||||
<code>m[1]</code> is the return stack index. Both are used as integer
|
||||
offsets into <code>m</code>. Both are kept in <code>m</code>, instead of
|
||||
as separate pointers, because they are then accessible to
|
||||
<code>first</code> programs, which is a crucial property of
|
||||
<code>first</code>. Similarly the way words are stored in the dictionary
|
||||
is not obvious, so it can be difficult to follow exactly what the
|
||||
<p><code>first</code> is obfuscated in several ways. Some minor obfuscations like
|
||||
<code>&w[&m[1]][s]</code> for <code>s+m[w+1]</code> were in the original source but are no longer
|
||||
because, apparently, ANSI doesn’t allow it (<code>gcc -ansi -pedantic</code> doesn’t mind
|
||||
it, though.)</p>
|
||||
<p>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
|
||||
<code>register</code> allocate it.)</p>
|
||||
<p>More significant are the design obfuscations. <code>m[0]</code> is the “dictionary
|
||||
pointer”, used when compiling words, and <code>m[1]</code> is the return stack index. Both
|
||||
are used as integer offsets into <code>m</code>. Both are kept in <code>m</code>, instead of as
|
||||
separate pointers, because they are then accessible to <code>first</code> programs, which
|
||||
is a crucial property of <code>first</code>. 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.</p>
|
||||
<p>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 <code>first</code> 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?” <a
|
||||
href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a>
|
||||
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 be
|
||||
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.)</p>
|
||||
<h3 id="what-exactly-is-first-then">What exactly is <code>first</code>,
|
||||
then?</h3>
|
||||
<p><code>first</code> is a tiny interpreter which implements a
|
||||
sufficient pseudo-subset of <a
|
||||
href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a>
|
||||
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.</p>
|
||||
<p>I believe <code>first</code> is close to the smallest amount of code
|
||||
possible to get this effect <em>using forth-style primitives</em>, 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
|
||||
<p>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 <code>first</code> 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?”
|
||||
<a href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a> 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 be 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.)</p>
|
||||
<h3 id="what-exactly-is-first-then">What exactly is <code>first</code>, then?</h3>
|
||||
<p><code>first</code> is a tiny interpreter which implements a sufficient pseudo-subset of
|
||||
<a href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a> 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.</p>
|
||||
<p>I believe <code>first</code> is close to the smallest amount of code possible to get this
|
||||
effect <em>using forth-style primitives</em>, 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
|
||||
<code>first</code> was included.</p>
|
||||
<p>THIRD is sorta slow, because <code>first</code> has so few primitives
|
||||
that many things that are primitives in <a
|
||||
href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a>
|
||||
(like swap) take a significant amount of time in THIRD.</p>
|
||||
<p>When you get the <code>Ok.</code> message from <code>third</code>,
|
||||
try out some sample <a
|
||||
href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a>
|
||||
code (<code>first</code> has no way of knowing if keyboard input is
|
||||
waiting, so it can’t actually prompt you in a normal way. It only prints
|
||||
<code>'Ok.'</code> after you define a word).</p>
|
||||
<div class="sourceCode" id="cb11"><pre
|
||||
class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span> 3 + . cr</span></code></pre></div>
|
||||
<p>THIRD is sorta slow, because <code>first</code> has so few primitives that many things that
|
||||
are primitives in
|
||||
<a href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a> (like swap)
|
||||
take a significant amount of time in THIRD.</p>
|
||||
<p>When you get the <code>Ok.</code> message from <code>third</code>, try out some sample
|
||||
<a href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a> code
|
||||
(<code>first</code> has no way of knowing if keyboard input is waiting, so it can’t actually prompt
|
||||
you in a normal way. It only prints <code>'Ok.'</code> after you define a word).</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span> 3 + . cr</span></code></pre></div>
|
||||
<p>(which adds 2 and 3, and print the result and a newline.)</p>
|
||||
<p>THIRD responds:</p>
|
||||
<pre><code>5</code></pre>
|
||||
@@ -312,115 +291,66 @@ class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#
|
||||
test</code></pre>
|
||||
<p>and THIRD responds</p>
|
||||
<pre><code>1 2 3 4 5 6 7 8 9 10</code></pre>
|
||||
<p>When in <code>THIRD</code>, you can see how much space you’re
|
||||
currently using by typing:</p>
|
||||
<p>When in <code>THIRD</code>, you can see how much space you’re currently
|
||||
using by typing:</p>
|
||||
<pre><code>here .</code></pre>
|
||||
<p>The number THIRD replies with is the number of machine words
|
||||
(<code>int</code>s) that the dictionary (the first code) takes up, plus
|
||||
the 512 <code>int</code>s for the return stack. If you compile the basic
|
||||
THIRD system without the help word (strings take up one <code>int</code>
|
||||
per character in the string!), you should find that you’re using around
|
||||
<p>The number THIRD replies with is the number of machine words (<code>int</code>s) that the
|
||||
dictionary (the first code) takes up, plus the 512 <code>int</code>s for the return stack.
|
||||
If you compile the basic THIRD system without the help word (strings take up one
|
||||
<code>int</code> per character in the string!), you should find that you’re using around
|
||||
1000 <code>int</code>s (plus the return stack).</p>
|
||||
<p>Thus THIRD gives you a relatively complete <a
|
||||
href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a>
|
||||
system in less than 700 chars of C source + about 1000 <code>int</code>s
|
||||
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.</p>
|
||||
<p>Software Construction Company gets credit for rekindling my interest
|
||||
in FORTH and thus indirectly inspiring me to write this program.</p>
|
||||
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
|
||||
License:</h2>
|
||||
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
|
||||
Reserved. You are free to share and adapt this file under the terms of
|
||||
this license:</p>
|
||||
<p>Thus THIRD gives you a relatively complete
|
||||
<a href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a> system in
|
||||
less than 700 chars of C source + about 1000 <code>int</code>s 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.</p>
|
||||
<p>Software Construction Company gets credit for rekindling my interest in FORTH
|
||||
and thus indirectly inspiring me to write this program.</p>
|
||||
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
|
||||
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
|
||||
You are free to share and adapt this file under the terms of this license:</p>
|
||||
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
|
||||
<p>For more information, see:
|
||||
https://creativecommons.org/licenses/by-sa/4.0/</p>
|
||||
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
|
||||
|
||||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
|
||||
|
||||
<h1 id="inventory-for-1992buzzard.2"><a name="inventory"></a>Inventory
|
||||
for 1992/buzzard.2</h1>
|
||||
<h1 id="inventory-for-1992buzzard.2"><a name="inventory"></a>Inventory for 1992/buzzard.2</h1>
|
||||
<p><a href="#top">Jump to top</a></p>
|
||||
<h2 id="primary-files">Primary files</h2>
|
||||
<ul>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.c">buzzard.2.c</a>
|
||||
- entry source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/Makefile">Makefile</a>
|
||||
- entry Makefile</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.alt.c">buzzard.2.alt.c</a>
|
||||
- alternative source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.orig.c">buzzard.2.orig.c</a>
|
||||
- original source</li>
|
||||
<li><a href="buzzard.2.README.html">buzzard.2.README.html</a> - author
|
||||
description of files</li>
|
||||
<li><a href="buzzard.2.design.html">buzzard.2.design.html</a> - about
|
||||
the FORTH language</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/try.alt.sh">try.alt.sh</a>
|
||||
- how to run alternative code</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/try.sh">try.sh</a>
|
||||
- how to run</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo1.1st">demo1.1st</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo1.th">demo1.th</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo2.th">demo2.th</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo3.th">demo3.th</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo4.th">demo4.th</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo5.th">demo5.th</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo6.th">demo6.th</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/help.th">help.th</a>
|
||||
- FORTH source</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/third">third</a>
|
||||
- the third source</li>
|
||||
<li><a href="1992_buzzard.2.tar.bz2">1992_buzzard.2.tar.bz2</a> -
|
||||
download entry source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.c">buzzard.2.c</a> - entry source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/Makefile">Makefile</a> - entry Makefile</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.alt.c">buzzard.2.alt.c</a> - alternative source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.orig.c">buzzard.2.orig.c</a> - original source</li>
|
||||
<li><a href="buzzard.2.README.html">buzzard.2.README.html</a> - author description of files</li>
|
||||
<li><a href="buzzard.2.design.html">buzzard.2.design.html</a> - about the FORTH language</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/try.alt.sh">try.alt.sh</a> - how to run alternative code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/try.sh">try.sh</a> - how to run</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo1.1st">demo1.1st</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo1.th">demo1.th</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo2.th">demo2.th</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo3.th">demo3.th</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo4.th">demo4.th</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo5.th">demo5.th</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/demo6.th">demo6.th</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/help.th">help.th</a> - FORTH source</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/third">third</a> - the third source</li>
|
||||
<li><a href="1992_buzzard.2.tar.bz2">1992_buzzard.2.tar.bz2</a> - download entry source</li>
|
||||
</ul>
|
||||
<h2 id="secondary-files">Secondary files</h2>
|
||||
<ul>
|
||||
<li><a href="index.html">index.html</a> - entry home page</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/.entry.json">.entry.json</a>
|
||||
- description of entry in JSON</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/.gitignore">.gitignore</a>
|
||||
- list of files that should not be committed under git</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/.entry.json">.entry.json</a> - description of entry in JSON</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
|
||||
<li><a href=".path">.path</a> - directory path from top directory</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/README.md">README.md</a>
|
||||
- markdown source for index.html</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.README.md">buzzard.2.README.md</a>
|
||||
- markdown source for buzzard.2.README.html</li>
|
||||
<li><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.design.md">buzzard.2.design.md</a>
|
||||
- markdown source for buzzard.2.design.html</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/README.md">README.md</a> - markdown source for index.html</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.README.md">buzzard.2.README.md</a> - markdown source for buzzard.2.README.html</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.2/buzzard.2.design.md">buzzard.2.design.md</a> - markdown source for buzzard.2.design.html</li>
|
||||
</ul>
|
||||
|
||||
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
|
||||
|
||||
Reference in new issue
Block a user