Forth

Forth Command Line and Programming Language.

Configurable Features

In order to accommodate the needs of various embedded systems certain features of the Embeddable Forth Command Interpreter are configurable at compile time. The idea is to not burden a system with features it does not use. In fact it might be highly undesirable to have features that are not absolutely necessary e.g. if the software is used in such a product that requires extensive validation for safety or other regulation purposes. In general features that are not used just should not be there at all.

Other features such as the maximum size of the dictionary and stack space are highly usage dependent.

Compile-time Configuration

Compile time configuration is done by editing the C header file forth_features.h before compiling the system.

// The size of the terminal buffer.
#define TIB_SIZE 256

// The size of the Forth Dictionary in CELLs.
// Because of the execution model it should be
// less than 64K cells (256 KB on a 32bit system).
#define FORTH_DICTIONARY_SIZE 4096

// The number of user defined per execution thread variables
// (known as USER variables in Forth parlance).
// #undef this to disable USER variables altogether.
#define FORTH_USER_VARIABLES 256

// #undef this if you don't want file access words.
#define FORTH_INCLUDE_FILE_ACCESS_WORDS 1

// #undef this if you don't want memory allocation words.
#define FORTH_INCLUDE_MEMORY_ALLOCATION_WORDS 1

// Some macros to allocate the C style (0 terminated) strings
// for file names.
#if defined(FORTH_INCLUDE_FILE_ACCESS_WORDS)
#       define FORTH_FILE_INPUT_BUFFER_LENGTH 256
#       define FORTH_ALLOCATE_CNAME(PTR, LEN) (strndup)((PTR), (LEN))
#       define FORTH_FREE_CNAME(X) free((X))
#endif

// #define this if you don't want the Forth compiler (interpreter only).
#undef FORTH_DISABLE_COMPILER

// #undef this if you don't want the word MS.
#define FORTH_INCLUDE_MS 1
// #undef this if you don't want the word TIME&DATE
#define FORTH_INCLUDE_TIME_DATE 1

// #undef this to disable stack underflow/overflow checking.
#define FORTH_STACK_CHECK_ENABLED

// #define this to disable ALL double number and mixed arithmetic,
// no D+ -es, M+ -es or */-s, not even #.
#undef FORTH_NO_DOUBLES

// #undef this if you do not want to allow C-style hex numbers
// that start with 0x
#define FORTH_ALLOW_0X_HEX 1

// If the application requires extra fields in the run time context
// #define this to list them.
// See the telnet implementation in the ZedBoard example for an example.
#undef FORTH_APPLICATION_DEFINED_CONTEXT_FIELDS

Run-time Configurable fields in the Context

The Run time context passed to the function forth() has several per thread fields that need to be properly initialized. A full list can be obtained from the source file forth.h. The most noteworthy fields that need to be initialized by the application are the following:

  • Sp, sp0, sp_min and sp_max: The current, initial, minimum and maximum values of the data stack pointer.
  • Rp, rp0, rp_min and rp_max: The current, initial, minimum and maximum values of the return stack pointer.
  • Terminal_width: The width of the terminal in characters.
  • Terminal_height: The height of the terminal in characters.

The following are function pointers that implement terminal I/O operation and can in fact vary from per thread of execution if e.g. one thread is talking to a serial line and another one is talking to a network connection. They are the implementation details of the Forth words listed in the corresponding comment. There really isn’t any one size fits all solution as different embedded systems might use drastically different means to talk to the outside world (if at all) and some operations might be unimplementable on some of them.

// PAGE -- If the device cannot do it set to to 0.
int (*page)(struct forth_runtime_context *rctx);

// AT-XY -- If the device cannot do it set to to 0.                                                       
int (*at_xy)(struct forth_runtime_context *rctx, forth_cell_t x, forth_cell_t y); 
                      
// TYPE
int (*write_string)(struct forth_runtime_context *rctx, const char *str, forth_cell_t length); 
         
// CR
int (*send_cr)(struct forth_runtime_context *rctx);           
                                          
// ACCEPT
forth_scell_t (*accept_string)(struct forth_runtime_context *rctx, char *buffer, forth_cell_t length); 
 
// KEY
forth_cell_t (*key)(struct forth_runtime_context *rctx);        
                                        
// KEY?
forth_cell_t (*key_q)(struct forth_runtime_context *rctx);   
                                           
// EKEY
forth_cell_t (*ekey)(struct forth_runtime_context *rctx);    
                                           
// EKEY?
forth_cell_t (*ekey_q)(struct forth_runtime_context *rctx);  
                                          
// EKEY>CHAR
forth_cell_t (*ekey_to_char)(struct forth_runtime_context *rctx, forth_cell_t ekey);
                    

There are several other filed in the runtime context but they are either internal to the Forth system or should be always initialized the same way for other reasons. Probably best is to just follow the examples in the source code.

Last updated: April 20, 2014