A Simple Forth System for Linux on i386 and ARM CPUs written in assembly language http://www.call-with-current-continuation.org/forth/
Uriel 5f2c919015 add files 2 years ago
README add files 2 years ago
a.out.f add files 2 years ago
blocks.f add files 2 years ago
core.f add files 2 years ago
cross.f add files 2 years ago
ed.f add files 2 years ago
elf.f add files 2 years ago
ff-arm add files 2 years ago
ff-arm.s add files 2 years ago
ff-i386 add files 2 years ago
ff-i386-plan9 add files 2 years ago
ff-i386-plan9.s add files 2 years ago
ff-i386.s add files 2 years ago
forth add files 2 years ago
meta-install.f add files 2 years ago
meta.f add files 2 years ago
primitives.s add files 2 years ago
robots.f add files 2 years ago
stuff.f add files 2 years ago
words-gas.s add files 2 years ago
words-nasm.s add files 2 years ago
x-arm.f add files 2 years ago
x-i386-plan9.f add files 2 years ago
x-i386.f add files 2 years ago

README


ff - A Simple FORTH System
==========================



Introduction
------------

This is `ff`, an implementation of the Forth programming language for 32-bit
CPUs on Linux and Plan 9. `ff` is indirect-threaded and currently available for
x86 and ARM processors. It is kept intentionally simple to reduce size and
complexity to a minimum. Floating-point math and double-precision numbers are
not supported and only very limited I/O facilities are provided. On the other
hand, the machine-code portion is small and it should be very easy to port `ff`
to other architectures.

Installation
------------

`ff` is available in pre-compiled, binary form and requires no additional
libraries, so it is not necessary to build it to get going.

The following files are included in the distribution:

ff-i386 x86 executable
ff-arm ARM executable
ff-i386-plan9 x86 executable for Plan 9
README This file
ff-i386.s Assembler sources for x86 (NASM syntax)
ff-arm.s Assembler sources for ARM (GAS syntax)
primitives.s Primitive dictionary
words-nasm.s Bootstrapping core dictionary (NASM syntax)
words-gas.s Bootstrapping core dictionary (GAS syntax)
core.f Core dictionary sources
meta.f Meta-compiler sources
meta-install.f Meta-compiler installation
elf.f Meta-compiler (elf binary generation)
cross.f Meta-compiler (Plan 9 a.out binary generation)
stuff.f Miscellaneous words
blocks.f Block- and buffer words
ed.f Block-editor sources
robots.f A simple game
forth Tcl/Tk frontend
x-i386.f Settings for cross-compilation to x86
x-arm.f Settings for cross-compilation to ARM
x-i386-plan9.f Settings for cross-compilation to x86 on Plan 9

In case you want to build `ff-*` yourself you will need an assembler -
[NASM][1] for the x86 version and [GNU as][2] for ARM, the latter being usually
available on an ARM-based linux with development tools installed. ARM `ff` can
also easily be cross-assembled from a non-ARM Linux system.

The necessary build-commands look like this:

nasm -f elf ff-i386.s -o ff-i386.o
ld ff-i386.o -o ff-i386 # add "-m elf_i386" on an x86_64 system

Or, for an ARM based system:

as ff-arm.s -o ff-arm.o
ld ff-arm.o -o ff-arm

Note that this creates only a minimal Forth system, sufficient to run the
metacompiler. To generate or re-generate a complete binary, start the initial
executable and enter:

include meta.f
include elf.f
include meta-install.f
include core.f
<ARCH> msave ff
bye

where `<ARCH>` should be either `i386` or `arm`, depending on the system this
is running on.

On Plan 9, re-compilation is slightly different:

include meta.f
include a.out.f
include meta-install.f
include core.f
msave ff
bye

The C library (`libc`) is not used, `ff` directly invokes Linux or Plan 9
system-calls.

Cross-compilation is similar, but needs an additional file with hard-coded
addresses, together with binaries containing the target-specific machine code
of the kernel in the `boot` directory. So, assuming `ff-arm` is available as
`boot/ff-arm`:

include meta.f
0 target-endianness \ if target and host have different byte-order
\ 0 = big, 1 = little
include elf.f
include x-arm.f \ or "include x-i386.f"
include meta-install.f
include core.f
arm msave ff \ or "i386 msave ff"
bye

Again, replace `elf.f` with `a.out.f` and drop the argument to `msave` on
Plan 9. Note that ARM/Plan 9 is currently not supported.

Porting to other platforms should be straightforward, since the assembler
portion is quite small. Porting the system to embedded systems should also
don't present any problems - just add or remove primitive words in `ff-*.s` as
necessary and metacompile.

Some additional files and scripts for building and cross-compilation are
avaialble in the [`ff` development repository][5].


Usage
-----

`ff` reads Forth commands from stdin, interpreting words as they are parsed. A
subset of the [Forth ANSI standard][3] is supported, see below for a
description of all words that are available.

All input is parsed case-sensitively, and the base dictionary contains
lowercase words.

If one or more command-line arguments are given, then the first argument is
loaded as an image-file (using `bload`.)

The `forth` script implements a simple text-based front-end for `ff`, and is
written in Tcl/Tk. It provides a very basic *terminal* and implements basic
text-editing functionality. It defaults to invoking a binary named `ff` which
should be in the `PATH` (if it isn't copy or symlink the `ff-*` binary for your
architecture)

Command-line options that the `forth` script accepts:

-background COLORNAME select background color
-foreground COLORNAME select foreground color
-fontname FONTNAME select font
-fontsize FONTSIZE select fontsize
-execute FILENAME load Tcl source from FILENAME at startup
-ff FILENAME run FILENAME instead of the default "ff"
-cd DIRECTORY change working directory to DIRECTORY
-init STRING Forth code to be executed on startup
-image FILENAME Load image-file on startup (uses "-init")

Output from `ff` is appended to any text in the window. The character `^L`
(ASCII 12) is handled specially and clears the window.

`RETURN` will send the current selection to the Forth interpreter, or the
current line if no text is currently selected. Pressing the `Insert` key will
enter *hold* mode, which means `RETURN` will just insert a newline, without
executing any code. Pressing `Insert` again will send all text beginning from
the location where `Insert` was first pressed up to the current cursor position
and disable hold mode.

Pressing the right mouse button on a word in the window will execute the Forth
statement `command <word>`. `command` is a deferred word defined in `stuff.f`
that can be used to implement a poor man's menu system by just right-clicking
words in the window.

Pressing `Escape` terminates the Forth interpreter, pressing it again exits
the front-end.

The function keys can be bound to text that is either inserted at the current
position, or (if it ends with a newline) immediately executed. To bind a key to
a particular sequence, select the text you want to bind and press `Control-F<n>`,
where `F<n>` is the function key you want to change.

`Control-Up` and `Control-Down` move the currently shown screen, when the
block and editor extensions are loaded.

If a file called `.forth` exists in the `HOME` directory, it is loaded before
startup and can be used to customize the front-end. Study the source code for
`forth` to learn more about it.

If the Forth system crashes, the background color turns to black and a message
is printed. Press `RETURN` to restart.


Unicode support
---------------

Partial UTF-8 support is provided: `emit`, `char` and `[char]` encode and
decode UTF-8 sequences correctly. `key` does not. The front-end allows entering
unicode code-points using the `Delete` key, which accepts either a hexadecimal
code-point or a named character. The latter can be defined in your `~/.forth`
file by adding a definition for the `snippets` variable, holding lists of
2-element lists:

set snippets {
{alpha "\u03b1"}
...
}


Builtin words
-------------

- Standard words (ANS)

Defined in the core system:

`!` `#` `#>` `<#` `#s` `'` `(` `*` `+` `+!` `+loop` `,` `-` `.` `."` `.r` `/`
`/mod` `0<` `0<>` `0=` `0>` `1+` `1-` `2*` `2/` `2drop` `2dup` `:` `;` `<` `<#`
`<>` `=` `>` `>body` `>in` `>r` `?do` `?dup` `@` `[` `[']` `[char]` `\` `]`
`abort` `abort"` `abs` `accept` `again` `align` `aligned` `allot` `and` `base`
`begin` `bl` `blk` `c!` `c,` `c@` `cell+` `cells` `char` `clear` `close-file`
`cmove` `cmove>` `compare` `constant` `count` `cr` `create` `decimal` `defer`
`depth` `do` `drop` `dup` `else` `emit` `erase` `execute` `exit` `false` `fill`
`find` `h` `here` `hex` `hold` `i` `if` `immediate` `include` `included`
`invert` `is` `j` `key` `list` `literal` `load` `loop` `lshift` `max` `min`
`mod` `negate` `nip` `off` `on` `open-file` `or` `over` `pad` `page` `pick`
`quit` `r/o` `r/w` `r>` `r@` `read-file` `recurse` `refill` `repeat`
`reposition-file` `reset` `restore-input` `rot` `rshift` `s"` `save-input`
`scr` `search` `sign` `sliteral` `space` `spaces` `state` `string` `swap`
`then` `tib` `true` `tuck` `type` `u.` `u.r` `unloop` `until` `unused`
`variable` `w/o` `while` `within` `word` `write-file` `xor` `does>` `current`

Defined in the source files `stuff.f` and `blocks.f`:

`2@` `2!` `2>r` `2r>` `?` `-trailing` `.s` `:noname` `/string` `also` `block`
`buffer` `buffer:` `case` `context` `current` `definitions` `dump`
`empty-buffers` `endcase` `endof` `forget` `forth` `list` `load` `marker` `of`
`only` `order` `postpone` `previous` `scr` `thru` `update` `vocabulary` `words`

- Notes:

- `while` is only allowed once inside a `begin`/`repeat` construct.

- `<#`, `#`, `#s` and `#>` only handle single-precision numbers.

- There are no "state-smart" words. `is`, `."` and `s"` are intended
to be used inside colon definitions.

- Non-standard core words

`2nip ( x y -- y )`

Drops the 2nd item on the stack.

`<builds ( | <word> -- )`

Compile-time part of `<builds ... does>` pair. In other Forth systems
`create` is normally used for this.

`>limit ( -- a )`

Variable holding the end-index in the text-input-buffer (TIB).

`?stack ( -- )`

Aborts on stack-underflow.

`(.) ( n1 -- a n2 )`

Convert signed number to string and return address and length.

`_start ( -- a )`

Pushes address of machine-code entry-point.

`_end ( -- a )`

Pushes end-address of machine-code section.

`args ( ... -- )`

Pushes a pointer to an array of cells, holding the number of
command line arguments, followed by pointers to zero-terminated
strings, one for each command-line argument (including the program
name), terminated by 0.

`boot ( ... -- )`

Completely reinitializes the system and invokes `cold`.

`bload ( a n -- )`

Loads a memory-image from `<filename>` restoring the state at
which the image was last saved with `save-image`. Note that
image-files are not portable and depend on the executable being
exactly the same at both save- and load-time. After loading the
image, the deferred word `startup` is invoked.

`bye ( -- )`

Terminates `ff`.

`c" ( | ..." -- a )`

Stores a counted string in the dictionary and pushes its
address. To be used in interpreted mode.

`cas ( a1 x y -- f )`

Perform an atomic _compare and swap_ operation on address `a1`,
i.e. compares the contents of the given address with `x` and, if
it is equal, replaces the stored value with `y`,
atomically. Pushes a flag indicating whether the operation
succeeded.

`cold ( ... -- )`

Performs a "cold" start, completely re-initializing the system.

`crash ( ... -- )`

Called when an uninitialized deferred word is invoked.

`halt ( n -- )`

Terminate with exit-code `n`.

`heaptop ( -- a )`

Variable holding the address of the top of the available heap.

`interpret ( | ... -- )`

Interprets words from the text-input-buffer (TIB).

`load-image ( | <filename> -- )`

Invokes `bload` with the given filename.

`mmap ( a1 -- a2 )`

Invokes the Linux `mmap` system call. `a1` should be the address
of an `mmap_arg_struct` holding the parameters. See [this page][4]
for more details. This word is a no-op on Plan 9.

`number ( a n1 -- n2 -1 | a n1 0 )`

Parses number given by string and either pushes the parsed
number and `true` or keeps the argument items, pushing `false`,
if the number is not a valid integer.

`parse ( c | ... -- a )`

Reads the next characters in the input-stream until character
`c` is encountered and returns the address of a counted
string. Note that this word is not ANSI compatible (it returns a
counted string.)

`prompt ( -- )`

A deferred word that prints the prompt that is shown when the
interpreter waits for input. The default prints ` ok` and advances
to a new line.

`query ( -- )`

Reads a new line from stdin into the TIB.

`reveal ( -- )`

Exposes the most recent item in the dictionary (see also
`smudge`.)

`rshifta ( n1 n2 -- n3 )`

Performs an arithmetic shift of `n1` by `n2` bits.

`s0 ( -- a )`

Variable holding the initial stack-pointer.

`s@ ( -- a )`

Pushes the current stack-pointer.

`save-image ( | <filename> -- )`

Saves the current dictionary to `<filename>`.

`signum ( n1 -- n2 )`

Pushes -1, 0 or 1, depending on whether `n1` is negative, zero
or positive.

`smudge ( -- )`

Hides the most recent dictionary entry.

`startup ( -- )`

Invoked after a binary image is loaded. The default behaviour is to print
`"ok "` and invoke `abort`.

`u/mod ( u1 u2 -- u3 u4 )`

Like `/mod`, but treats arguments as unsigned numbers.

`utfdecode ( a1 -- a2 c )`

Decodes the UTF-8 byte sequence at address `a1` and returns the address
directly after the byte sequence and the unicode code-point.

`utfencode ( a c -- a n )`

Encodes the unicode code-point `c` as an UTF-8 byte sequence at address
`a`, and returns the target address and the number of bytes.

- Optional words

Some additional words are available in the source files
`stuff.f`. Read that file to learn more about what's included.


The Block-file Editor
---------------------

The system includes an optional simple command-based block-editor in
the file `ed.f`. See below for a list of available editor
commands. Blocks are stored in a file called `blockfile`, which must
reside in the current working directory. Note that the editor needs
the words in `blocks.f`.

To create a blockfile, use the following commands

# creates a blank file of 1024 blocks:
dd if=/dev/zero bs=1024 count=1024 | tr '\000' ' ' >blockfile

The editor maintains two buffers, together with the current edited
block (`scr`): the *insertion-buffer* and the *find-buffer*. The
former is used in commands that add or insert text, the latter holds
text that is searched.

The editor is provided in source form in the file `ed.f`. The
ANS block- and buffer-related words can be found in `blocks.f`.

All editor words exist in the `editor` vocabulary, so execute `editor`
before using them.

- Editor commands:

`b ( -- )`

List previous screen.

`copy ( n1 n2 -- )`

Copies contents of block `n1` to block `n2`.

`cut ( -- )`

Deletes everything on the line, starting from the current
position.

`d ( [| ...] -- )`

Deletes given text (or last found text).

`e ( -- )`

Deletes last found text.

`f ( [| ...] -- )`

Searches given text (or contents of the find-buffer) in current
line.

`i ( [| ...] -- )`

Inserts given text (or contents of the insert-buffer) at current
position.

`index ( n1 n2 -- )`

Shows first lines of blocks in given range.

`k ( -- )`

Swaps contents of insert- and find-buffer.

`l ( -- )`

Clears window and lists current screen.

`n ( -- )`

Lists next screen.

`p ( [| ...] -- )`

Replaces current line with given text (or contents of the
insert-buffer).

`r ( [| ...] -- )`

Replaces last found text with given text (or contents of the
insert-buffer).

`s ( n [| ...] -- n )`

Searches given text (or contents of find-buffer) in current
screen and all blocks up to and including `n`.

`show ( n1 n2 -- )`

Lists blocks in the given range.

`t ( n -- )`

Selects line `n`.

`till ( [| ...] -- )`

Erases all text from the current position to the position where
the given text (or the contents of the find-buffer) is found in
the current line.

`u ( [| ...] -- )`

Inserts given text (or contents of insert-buffer) below the
current line, shifting remaining lines down.

`wipe ( -- )`

Blanks the current screen.

`x ( -- )`

Removes current line and stores it in the insertion-buffer, scrolls
lines below up.


Tips and Tricks
---------------

- Creating a custom *image*

To create a personal development system that contains more than the
core wordset, use `save-image` to write the dictionary to a file:

include stuff.f \ extras
include blocks.f \ block-words
include ed.f \ block-editor
save-image myimage

This generates `myimage`, that, when loaded, holds the same
dictionary that was in effect at the time the image was saved. To
load this image enter:

load-image myimage

Or, if you want to use it with the front-end, start the latter like
this:

forth -image myimage

- Image files can be executed directly, as they are prefixes with
a *she-bang* line of the form `#!/usr/bin/env ff`. A custom
application can be created like this:

$ ff
: foo ." hello, world!" cr ;
ok
:noname ['] foo is startup ; execute
ok
save-image hello
ok
bye
$ chmod +x hello
$ hello
hello, world!
$

- By using the `-ff` front-end option, nothing prevents you from
invoking a forth-interpreter on another machine:

forth -ff "ssh <remotemachine> ff"

Alternatively, put this into your `~/.forth`:

set forth "ssh <remotemachine> ff"

- The initial heap/dictionary space is allocated to roughly 10 MB. To
change this setting, modify the value of the constant `HEAP_SIZE` in
`ff-<ARCH>.s` and rebuild everything. In the same manner the sizes
of the data- and return stack can be adjusted by modifying
`SSTACK_SIZE` or `RSTACK_SIZE`.

- Don't use tab (ASCII 9) characters - they are not treated as
any other non-whitespace character.


List of all available words
---------------------------

! ( x a -- ) primitive
!+ ( a1 x -- a2 ) optional

?exit ( f -- ) optional

" ( ..." -- a n )

# ( u1 -- u2 )
#> ( u1 -- a n )
#s ( u -- n )

' ( <word> -- xt )

( ( ...) -- ) immediate
(+loop) ( n -- ) primitive
(:) ( -- ) primitive
(.) ( n1 -- a n2 )
(?abort) ( f a n -- )
(abort) ( ... -- )
(constant) ( -- x ) primitive
(deferred) ( -- ) primitive
(do) ( n1 n2 -- ) primitive
(else) ( -- ) primitive
(if) ( n1 -- ) primitive
(literal) ( -- n ) primitive
(loop) ( -- ) primitive
(sliteral) ( -- a n ) primitive
(variable) ( -- a) primitive

* ( n1 n2 -- n3 ) primitive

+ ( n1 n2 -- n3 ) primitive
+! ( n a -- )
+loop ( n -- ) immediate

, ( x -- )
," ( | ..." -- ) optional

- ( n1 n2 -- n3 ) primitive
-trailing ( a n1 -- a n2 ) optional

. ( n -- )
." ( | ..." -- ) immediate
.( \( | ...) -- ) immediate optional
.buffers ( -- ) optional
.s ( -- )
.r ( n1 n2 -- )

/ ( n1 n2 -- n3 )
/mod ( n1 n2 -- n3 n4 ) primitive
/string ( a1 n1 -- a2 n2 ) optional

0< ( n -- f )
0<> ( n -- f )
0= ( n -- f )
0> ( n -- f )

1+ ( n1 -- n2 )
1- ( n1 -- n2 )
2* ( n1 -- n2 )
2/ ( n1 -- n2 )
2@ ( a -- x y )
2! ( x y a -- )
2>r ( x y -- )
2drop ( x y -- )
2dup ( x y -- x y x y )
2nip ( x y z -- z )
2r> ( -- x y )
2swap ( x y z q -- z q x y )

: ( | <word> -- )
:noname ( | ... -- xt ) optional

; ( -- ) immediate

< ( n1 n2 -- f ) primitive
<# ( -- )
<> ( n1 n2 -- f )
<builds ( | <word> -- )

= ( n1 n2 -- f ) primitive

> ( n1 n2 -- f ) primitive
>body ( a1 -- a2 )
>in ( -- a )
>limit ( -- a )
>r ( x -- ) primitive

? ( a -- )
?do ( n1 n2 -- )
?dup ( x -- x [x] )
?stack ( -- )

@ ( a -- x ) primitive
@+ ( a1 -- a2 x ) optional

[ ( -- )
['] ( | <word> -- xt ) immediate
[char] ( | <char> -- c ) immediate

\ ( | ... -- ) immediate

] ( -- ) immediate

_end ( -- a ) primitive
_start ( -- a ) primitive

abort ( ... -- ) deferred
abort" ( f | ..." -- ) immediate
abs ( n -- u )
accept ( a n1 -- n2 )
again ( -- ) immediate
align ( -- )
aligned ( a1 -- a2 )
allot ( n -- )
also ( -- ) optional
and ( n1 n2 -- n3 ) primitive
args ( -- a )

b ( -- ) editor
base ( -- a )
begin ( -- ) immediate
bl ( -- c )
bload ( a n -- )
blank ( a n -- )
blk ( -- a )
block ( n -- a )
boot ( -- )
bounds ( a1 n -- a2 a1 ) optional
buffer ( n -- a )
buffer: ( n | <word> -- ) optional
bye ( -- )

c! ( c a -- ) primitive
c, ( c -- )
c@ ( a -- c ) primitive
c" ( | ..." -- a )
cas ( a x y -- f ) primitive
case ( x -- ) optional
cell+ ( a1 -- a2 )
cells ( n1 -- n2 )
char ( | <char> -- c )
clear ( ... -- ) primitive
close-file ( fd -- ior )
cmove ( a1 a2 n -- ) primitive
cmove> ( a1 a2 n -- ) primitive
cold ( ... -- )
command ( | <word> -- ) deferred optional
compare ( a1 n1 a2 n2 -- n3 )
constant ( x | <word> -- x )
context ( -- a ) optional
copy ( n1 n2 -- ) editor
count ( a1 -- a2 n )
cr ( -- )
crash ( -- )
create ( | <word> -- )
current ( -- ) primitive
cut ( -- ) editor

d ( | ... -- ) editor
decimal ( -- )
defer ( | <word> -- )
definitions ( -- ) optional
depth ( -- u )
do ( n1 n2 -- ) immediate
does> ( | ... -- a )
drop ( x -- ) primitive
dump ( a n -- )
dup ( x -- x x ) primitive

e ( -- ) editor
editor ( -- ) editor
else ( -- ) immediate
emit ( c -- )
emits ( c n -- )
empty-buffers ( -- )
endcase ( -- ) optional
endof ( -- ) optional
erase ( a n -- )
execute ( xt -- ) primitive
exit ( -- ) primitive

f ( | ... -- ) editor
false ( -- 0 )
fill ( a n c -- )
find ( a -- a 0 | xt 1 | xt -1 )
flush ( -- )
forth ( -- ) optional
forget ( | <word> -- ) optional

h ( -- a ) primitive
halt ( n -- ) primitive
heaptop ( -- a ) primitive
here ( -- a )
hex ( -- )
hold ( c -- )

i ( -- n ) primitive
i ( | ... -- ) editor
if ( f -- ) immediate
immediate ( -- )
include ( | <fname> -- ) primitive
index ( n1 n2 -- )
interpret ( -- )
invert ( n1 -- n2 )
is ( xt | <word> -- ) immediate

j ( -- n ) primitive
join ( -- ) editor

k ( -- ) editor
key ( -- c )

l ( -- ) editor
list ( n -- ) editor
literal ( n -- )
load ( n -- ) editor
load-image ( | <fname> -- )
loop ( -- ) immediate
lshift ( n1 u -- n2 ) primitive

max ( n1 n2 -- n1 | n2 )
marker ( | <word> -- ) optional
min ( n1 n2 -- n1 | n2 )
mmap ( a1 -- a2 ) primitive
mod ( n1 n2 -- n3 )

n ( -- ) editor
negate ( n1 -- n2 )
next-screen ( -- ) optional
nip ( x y -- y )
noop ( -- ) optional
number ( a n1 -- n2 -1 | a n1 0 )

of ( x -- ) optional
off ( a -- )
on ( a -- )
only ( -- ) optional
open-file ( a n1 n2 -- fd ior )
or ( n1 n2 -- n3 ) primitive
order ( -- ) optional
over ( x y -- x y x ) primitive

p ( | ... -- ) editor
pad ( -- a )
page ( -- )
parse ( c | ... -- a )
perform ( a -- ) optional
postpone ( | <word> -- ) optional
pick ( ... n -- x )
previous ( -- ) optional
previous-screen ( -- ) optional
prompt ( -- ) deferred

query ( -- )
quit ( ... -- )

r ( | ... -- ) editor
r/o ( -- n )
r/w ( -- n )
r> ( -- x ) primitive
r@ ( -- x ) primitive
random ( -- n ) optional
read-file ( a n1 fd -- n2 ior )
recurse ( -- )
refill ( -- f )
repeat ( -- ) immediate
reposition-file ( n fd -- ior )
reset ( -- ) primitive
restore-input ( ... n -- )
reveal ( -- )
rfind ( xt -- a|0 ) optional
rot ( n1 -- n2 )
rshift ( n1 u -- n2 ) primitive
rshifta ( n1 u -- n2 ) primitive

s ( n | ... -- n ) editor
s" ( | ..." -- a n ) immediate
s0 ( -- a )
s@ ( -- a ) primitive
save-image ( | <fname> -- )
save-input ( -- ... n )
scan ( a1 n1 c -- a2 n2 ) optional
scr ( -- a ) editor
search ( a1 n1 a2 n2 -- a3 n3 f )
see ( | <word> -- ) optional
seed ( -- a ) optional
show ( n1 n2 -- ) editor
sign ( n -- )
signum ( n1 -- n2 )
skip ( a1 n1 c -- a2 n2 ) optional
sliteral ( | ..." -- )
smudge ( -- )
space ( -- )
spaces ( n -- )
startup ( -- ) deferred
state ( -- a )
string ( c | ... -- )
string, ( a n -- ) optional
swap ( x y -- y x )

t ( n -- ) editor
then ( -- ) immediate
th ( n1 -- n2 ) optional
thru ( n1 n2 -- ) editor
tib ( -- a )
till ( | ... -- ) editor
true ( -- -1 )
tuck ( x y -- y x y )
type ( a n -- )

u ( | ... -- ) editor
u. ( u -- )
under+ ( n1 n2 n3 -- n4 n2 ) optional
unloop ( -- ) immediate primitive
until ( f -- ) immediate
unused ( -- u )
update ( -- )
utfdecode ( a1 -- a2 c )
utfencode ( a c -- a n )

variable ( | <word> -- )
vocabulary ( | <word> -- ) optional

w/o ( -- n )
while ( f -- ) immediate
wipe ( -- ) editor
within ( n1 n2 n3 -- f )
word ( c | <word> -- a )
words ( -- ) optional
write-file ( a n fd -- ior )

x ( -- ) editor
xor ( n1 n2 -- n3 )


Frontend Key-bindings
---------------------

The key-bindings match mostly the standard key-bindings in Tcl/Tk's `text`
widget:

Delete Toggle "hold" mode
<Arrow> Move insertion point
Sh-<Arrow> Move insertion point + extend selection
C-Left, C-Right Move insertion point by words
C-Sh-Left, C-Sh-Right Move insertion point by words + extend selection
C-Sh-Up, C-Sh-Down Move by paragraphs + extend selection
Next, Prior Move vertically one screenful
Sh-Next, Sh-Prior Move screenful + extend selection
C-Next, C-Prior Move horizontally one page without changing point
C-a Move to beginning of line
Home Move to beginning of text
C-e Move to end of line
End Move to end of text
C-Space Set selection anchor
C-Sh-Space Select from anchor to insertion point
C-/ Select all text
C-d Delete selection or one character
Backspace Delete selection or last character
M-d Delete next word
C-k Cut rest of line
M-Backspace Delete previous word
C-w Cut selection
C-t Transpose characters
C-z Undo
C-Sh-z Redo
C-+ Increase font size
C-- Decrease font size
Return Send current line to forth and insert newline
C-Up List previous block
C-Down List next block
Escape Terminate
Tab Indent or tab
Alt-w Copy current selection
Insert Insert unicode codepoint (hex or named character)
F1 Show this text



Memory map
----------

+-----------------------+-----------+-------------------------------------+
| Area | Size | Contains |
+-----------------------+-----------+-------------------------------------+
| machine code words | | ".text" section ("_start"..."_end") |
| primitive dictionary | | start of ".data" section |
| core dictionary | | |
| system variables | 16 | |
| tib | 1024 | |
| wordbuffer | 256 | |
| heapspace | | start of ".bss" section |
| : | | |
| | | |
| insert buffer | 1024 | if editor is loaded |
| find buffer | 1024 | |
| buffer space | 16 x 1024 | if block-words are loaded |
| return stack | 4096 | |
| parameter stack | 4096 | |
| end of heap | | Contents of variable "s0" |
+-----------------------+-----------+-------------------------------------+


Register Usage
--------------

+----------------+---------------+--------------+----------------------------------+
| Forth register | i386 register | ARM register | Meaning |
+----------------+---------------+--------------+----------------------------------+
| TOS | eax | r0 | Top of stack |
| SP | esp | r13 | Data-stack ptr (grows downwards) |
| RP | ebp | r14 | Return-stack ptr (grows upwards) |
| AP | esi | r12 | Address-pointer |
| W | edi | r11 | "Work" register (holds CFA) |
| | ebx, ecx, edx | r1 - r5 | Temporaries |
+----------------+---------------+--------------+----------------------------------+


License
-------

Copyright (c) 2015, Felix L. Winkelmann
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Contact
-------

If you have questions, suggestions, want to report bugs or comment on
the system, please don't hesitate to contact me at

` felix <at> call-with-current-continuation <dot> org `


[1]: http://nasm.us/

[2]: http://www.gnu.org/software/binutils/

[3]: http://www.taygeta.com/forth/dpans.html

[4]: http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html#mmap_arg_struct

[5]: http://bitbucket.org/bunny351/ff