SkillAgentSearch skills...

Ff

A Simple Forth System for Linux on i386 and ARM CPUs

Install / Use

/learn @8l/Ff
About this skill

Quality Score

0/100

Supported Platforms

Universal

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.

    `(.)

View on GitHub
GitHub Stars41
CategoryDevelopment
Updated3mo ago
Forks9

Languages

Forth

Security Score

72/100

Audited on Dec 30, 2025

No findings