    CHForth

    Forth Users Group (C) 1994


Table of contents

1. Introduction to CHForth
    1.1 Background
    1.2 Contents of CHForth
    1.3 Organisation of this manual

2. Installation
    2.1 Installation on your system
    2.2 Directories
    2.3 DOS interface
    2.4 CHF386.EXE
    2.5 Starting CHForth
    2.6 Leaving CHForth

3. Loading programs
    3.1 Loading blocks
    3.2 Loading textfiles
    3.3 More about loading
    3.4 Load words glossary

4. How to get help
    4.1 The helpfiles
    4.2 The file browser
    4.3 The referencer
    4.4 Help words glossary

5. Local variables
    5.1 Use of locals
    5.2 Internals of local variables
    5.3 More local types
    5.4 Local words glossary

6. Forget and forget fields
    6.1 FORGET
    6.2 MARKER
    6.3 Examples
    6.4 Forget words glossary

7. Numbers and strings
    7.1 Numbers
    7.2 Characters
    7.3 Strings
    7.4 Numbers and strings word glossary

8. Word lists
    8.1 WORDLIST and VOCABULARY
    8.2 Search order
    8.3 CHForth word lists
    8.4 Example
    8.5 Word list glossary

9. Vectors
    9.1 Vectors used by the system
    9.2 Examples
    9.3 Vector words glossary

10. Interpreter structure
    10.1 QUIT
    10.2 INTERPRET
    10.3 'INTERPRET
    10.4 'COMPILE
    10.5 Interpreter words glossary

11. Error recovery
    11.1 CATCH and THROW
    11.2 Examples
    11.3 Error messages
        11.3.1 Standard ANS Forth messages
        11.3.2 DOS messages
        11.3.3 Messages of this Forth system
    11.4 Error words glossary

12. The assembler
    12.1 Register use
    12.2 Examples
    12.3 Structures
    12.4 Assembler words glossary

13. How about flyer

14. Using doer:

15. Defining methods

16. The TO-concept

17. Interrupt handling
    17.1 Used interrupts
    17.2 Examples
    17.3 Interrupt words glossary

18. The decompiler
    18.1 What can be decompiled
    18.2 What can not be decompiled
    18.3 Examples
    18.4 Decompiler words glossary

19. The disassembler
    19.1 What can be disassembled
    19.2 What can not be disassembled
    19.3 Examples
    19.4 Disassembler words glossary

20. The viewer
    20.1 What can be viewed
    20.2 What can not be viewed
    20.3 Examples
    20.4 Viewer words glossary

21. The interface with DOS
    21.1 The DOS environment
    21.2 External ports
    21.3 The screen
    21.4 The DOS interface glossary

22. Maintenance of program files
    22.1 Generating new source files
    22.2 Library files
    22.3 Logging
    22.4 Glossary generation
    22.5 Maintenance words glossary

23. Turnkey programs
    23.1 Trimming the system
    23.2 Self running programs
    23.3 Examples
    23.4 Turnkey words glossary

24. CHForth internals
    24.1 Code space
    24.2 Header space
    24.3 List space
    24.4 String space
    24.5 Stack space
    24.6 DOS space

25. Examples

26. Main glossary

27. Alphabetical index of words

========================================
1. Introduction to CHForth


1.1 Background


1.2 Contents of CHForth


1.3 Organisation of this manual

========================================
2. Installation

To install, you need a fairly compatible PC or AT with at least
8086 or 8088 processor, 256 Kb memory above DOS and 1 Mb free on
your harddisk (It is possible to install the program on a 1.2 Mb
or 1.44 Mb floppy and with more experience it might be possible
on a 720 Kb or even a 360 Kb floppy system).


2.1 Installation on your system

First make a subdirectory with
    MD CHF.
It is not necessary to have this subdirectory in the root of your
C: drive, it can be anywhere in your computer system, even on a
ramdisk if you don't trust me.

Then type
    CD CHF
to go to the directory.

When the distribution floppy is in your A: drive type:
    A:PKUNZIP -d A:CHF125
to unpack the files. The A:'s can be B:'s in your system. The
name CHF125 can be different, it is the name of the .ZIP file on
the floppy.

To use the program you can follow two methods, the first is copy
the CHFORTH.EXE file and CHFORTH.CFG from the CHF\BIN directory
to a directory in your path, like C:\DOS or C:\BIN. The second is
to extend the PATH= command in your AUTOEXEC.BAT file with
...\CHF\BIN.

With a DOS editor like EDIT or EDLIN you may have to change the
following two lines in CHFORTH.CFG:
    S" c:\chf\lib" LIBPATH PLACE
    S" c:\chf\doc" HELPPATH PLACE
into for example:
    S" d:\programs\develop\forth\ansi\chf\lib" LIBPATH PLACE
    S" e:\helpfiles\programming\forth\ansi"    HELPPATH PLACE

You may also have to change the line
    S" c:\chf\lib" LIBPATH PLACE
in the file CHF\TURNKEY\CHFORTH.CFG


2.2 Directories

CHForth uses some directories, these are made automatically
during the installation.

In CHF\BIN are CHFORTH.EXE, the 8086 version, CHF386.EXE, the 386
version and the configuration file CHFORTH.CFG.

In CHF\DOC are the .HLP and .TXT files.

In CHF\LIB are library files

In CHF\MISC are some miscellaneous programs.

In CHF\SPEED are some benchmarks and .LOG files that show the
benchmarks on a 40 MHz 486DLC machine.

In CHF\TURNKEY are some application programs in source form.


2.3 DOS interface

In the CHFORTH.CFG are provided some interfaces with DOS.

S" "            DOS: OS         -- Go to the operating system for a while
S" dir"         DOS: DIR        -- This looks familiar
\ S" copy"      DOS: COPY       -- Idem
\ S" ren"       DOS: REN        -- Ditto
S" list"        DOS: L          -- View a file
S" sz"          DOS: SZ         -- Tom Zimmer's editor
S" ne"          DOS: NE         -- Peter Norton's editor
S" nc"          DOS: SHELL      -- Alias OS exists already
S" chforth"     DOS: CHFORTH    -- Load another copy, probably useless
S" ts"          DOS: TS         -- If you have this program
S" ts *.frt"    DOS: ST         -- Search text in *.FRT files
S" grep"        DOS: GREP       -- Idem
S" ls"          DOS: LS         -- My version of DIR, source in \TURNKEY

At the left is the name of the program or command as it is known
to DOS, after the word DOS: the name of the program as it is
known to CHForth. If you do not have the program NE.COM you can
delete that line. Then the file LIB\EDITOR.FRT will use SZ.COM as
the default editor. If you do not have TS.EXE delete those lines.
LS.EXE can be made by CHForth itself, see the chapter about
turnkey programs.


2.4 CHF386.EXE

If you do have a 386SX, 386DX, 486SX, 486DX or even a Pentium,
you can rename the file CHF386.EXE to CHFORTH.EXE and use this
program. The difference is in some arithmetic routines that now
use 32 bit aritmetic for speed and the shifting is more efficient
and you can use some 386 instructions in the assembler. The
program still runs in real or virtual 8086 mode, for 32 bit Forth
implementations, see the literature.


2.5 Starting CHForth

The file CHFORTH.EXE has to be in the current directory or a
directory mentioned in the DOS environment variable PATH or you
can prefix the name of the program with the path. See your DOS
manual if this is not clear. When you type CHFORTH at the prompt,
it tries to read the CHFORTH.CFG that is in the current directory
and else the one that is in the directory where CHFORTH.EXE is
found. In this way you can have different configuration files
that can be tailored to the need of the moment, for example you
can have different libraries and helpfiles in other paths than
the standard ones. When the configuration file is read, the word
.FREE (which is an option on the last line of the file) is
executed to give you some information about the size of the
program and how many bytes there are free in each of the three
segments. On the command line you can give parameters that have
to be normal Forth, like:
        CHFORTH in life
to load the program in the file LIFE.FRT. When the loading is
done, a diagnostics line is given, first three numbers giving the
bytes compiled in the three segments, the sum of it, the number
of bytes compiled per minute, the number of lines, the number of
lines per minute and then the count of seconds elapsed. These are
all since the loading of the configuration file.


2.6 Leaving CHForth

The standard way to leave CHForth is type BYE. This words takes
care to reset used interrupt vectors to their initial values (see
also chapter 17). The same is accomplished by typing ALT+Q, when
the module -accept is present.

You can also return with <number> HALT to return a 8 bit code to
DOS that can be tested with ERRORLEVEL, when you run CHForth in a
batch file. This also can be used in make files. When you press
ALT+X, CHForth terminates with a returncode of 1.
========================================
3. Loading programs

The normal way in Forth for compiling programs is loading them in
source form from disk. In CHForth this can be done by loading
blocks and by loading textfiles.


3.1 Loading blocks

This paragraph is for those that still use block files like in
the sixties and seventies.

First you have to include extensions for handling block files,
this can be done by typing at the DOS prompt the following line:
    C:\CHF\>chforth empty in blockext close save blocks bye

Now a program BLOCKS.EXE will be generated, of course the name is
arbitrary. When the file BLOKKEN.BLK exist in the current
directory, this program will automatically open that file at
startup. It is a blocks file organised in 100 blocks. The first
one can be loaded with
    1 LOAD .

When the file BLOKKEN.BLK is not present, a message is given but
this is not considered an error.

Some examples are in this file. You can browse through the file
by typing BROWSE that has its own help. A simple editor in
FIGFORTH style is loaded with the file blockext.frt.

Opening other files with extension .BLK is possible. Open an
other one with:
    S" MYBLOCKS" USE-BLOCKS
When the first screens of the file BLOKKEN.BLK have been loaded
with:
    1 LOAD
you can use now:
    OPEN MYBLOCKS

The use of CLOSE is optional when you open another file or when
you leave the program because it is present in OPEN and BYE .

It is also possible to create a new block file by:
    100 MAKE-BLOCKS-FILE MYBLOCKS
to create a file MYBLOCKS.BLK containing 100 blocks.

You can change the default extension for example:
    S" .SCR" BEXT$ PLACE

As I now seldom use blocks, further help is not available, try to
figure out the workings by reading the FigForth manual or the
source.


3.2 Loading textfiles

In Europe, already in the seventies, Forth used standard
operating system files, that could be edited, copied and printed
with programs already available in the system software.

This is the preferred way in CHForth. To load the file MYFILE.FRT
you can use a few methods:
    1) INCLUDE MYFILE.FRT
    2) IN MYFILE
    3) S" MYFILE.FRT" INCLUDED
The second is preferred and shorter. The default extension
.FRT is in the counted string at FEXT$, changing this is unwise.

Files from CHF\LIB can be loaded by:
    IN LIB\MYLIB
But the normal way is by
    NEEDS -MYLIB
as some programs depent on this procedure. The word NEEDS will
skip loading if the MARKER -mylib already is loaded. You may
leave out the minus sign, this is only to remember that the word
MARKER is the first defining word in this file and you can forget
the compiled words with -mylib .


3.3 More about loading

The files on the distribution disk use always .FRT as default
extension. So the extension is never mentioned to load files with
IN or NEEDS .
When an error occurs during loading and you have an editor
installed in the CHFORTH.CFG file for NE or SZ, typing WHAT gets
you in the editor on the offending line. Also some information
about the error is written to a file ERROR.LOG in the current
directory so you could perhaps determine what caused the error.


3.4 Load words glossary

FEXT$              "f-ext-string"                          EXTRA
    ( -- c-addr )
    c-addr is the address of a counted string containing the default
    extension of Forth text files.

IN                                                         EXTRA
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space
    and load the file with that name. If the length of name is
    zero, load the file that was previously load with IN .

INCLUDE                                                    EXTRA
    ( "name" -- )
    Skip leading delimiters. Parse name delimited by a space and
    load the file with that name. The appropriate extension must
    be included in name.

INCLUDE-FILE                                               FORTH
    ( fileid -- )
    Remove fileid from the stack. Save the current input source
    specification, including the current value of SOURCE-ID .
    Store fileid in SOURCE-ID . Make the file specified by fileid
    the input source. Store zero in BLK . Other stack effects are
    due to the words INCLUDEd.
    
    Repeat until end of file: read a line from the file, fill the
    input buffer from the contents of that line, set >IN to zero,
    and interpret.
    
    Interpretation begins at the file position where the next file
    read would occur.
    
    When the end of the file is reached, close the file and
    restore the input source specification to its saved value.
    
    An ambiguous condition exists if fileid is invalid, if an I/O
    exception occurs reading fileid, or an I/O exception occurs
    while closing fileid. When an ambiguous condition exists, the
    status (open or closed) of any files that were being
    interpreted is implementation defined.

INCLUDED                                                   FORTH
    ( c-addr u -- )
    Remove c-addr u from the stack. Save the current input source
    specification, including the current value of SOURCE-ID . Open
    the file specified by c-addr u, store the resulting fileid in
    SOURCE-ID and make it the input source.  Store zero in BLK .
    Other stack effects are due to the words INCLUDEd.
    
    Repeat until end of file: read a line from the file, fill the
    input buffer from the contents of that line, set >IN to zero,
    and interpret.
    
    Interpretation begins at the file position where the next file
    read would occur.
    
    When the end of the file is reached, close the file and
    restore the input source specification to its saved value.
    
    An ambiguous condition exists if the named file can not be
    opened, if an I/O exception occurs reading the file, or an I/O
    exception occurs closing the file. When an ambiguous condition
    exists, the status (open or closed) of any files that were
    being interpreted is implementation defined.

LOAD                                                       FORTH
    ( i*x u -- j*x )
    Save the current input source specification. Store u in BLK ,
    thus making block u the input source and setting the input buffer
    to encompass its contents, set >IN to zero, and interpret. When
    the parse area is exhausted, restore the prior input source
    specification. Other stack effects are due to the words LOADed.
    
    Exceptions -33, -34 or -35 will occur if u is zero, or is not
    valid block number.

NEEDS                                                      EXTRA
    ( name -- )
    Find name and when found continue. When not found, load the
    file with the same name (excluding a trailing minus sign) from
    the directory in LIBPATH .

THRU                                                       FORTH
    ( i*x u1 u2 -- j*x )
    LOAD the mass storage blocks numbered u1 through u2 in sequence.
    Other stack effects are due to the words LOADed.

========================================
4. How to get help

CHForth offers a number of ways to help the user during running
of the program. The tools available are helpfiles, a decompiler,
a viewer, a disassembler, a file browser and a referencer.


4.1 The helpfiles

In the directory CHF\DOC are some files with the extension .HLP.
These are normal textfiles. Do not change their structure, they
are generated with a glossary generator and use the word \G that
you will find in the source files (with extension .FRT). They are
used by the HELP command. If you can not remember the use of for
example the word DUP just type 'HELP DUP'.

FORTH> help dup
File: KERNEL.HLP
DUP                "dupe"                                  FORTH
    ( x -- x x )
    Duplicate x.

On top is the name of the helpfile and on the left on the next
line is the word looked after. It is sometimes followed by the
pronounciation in double quotes. When the helpfile is KERNEL.HLP
the word on the far right is FORTH or EXTRA, the wordlists in
which the definition is compiled. In other helpfiles it is the
name of the file in the CHF\LIB directory where the word is
defined.

When a full screen is displayed, HELP waits for a key press.
Pressing Esc stops, others will continue displaying the remaining
text.

Needed file: LIB\HELP.FRT


4.2 The file browser

You can look up words in files in the current directory by typing
SF followed by a string of characters, including spaces. For
example to find any occurence of the string 'SWAP DUP':

FORTH> sf swap dup
  1 BENCH.FRT       23                    DUP SWAP DUP ROT DROP 1 AND
  2 COREWARS.FRT   375    SWAP DUP @ 5 * SWAP CELL+          \ #bytes and st

On the left is the number of lines found, followed by the
filename, followed by the linenumber in the file and the line
itself is printed till the end of the screen line. Leading and
trailing spaces are significant.

The word SL does the same, but uses the files in CHF\LIB

The word LOOK must be followed with a filename, including the
extension and an optional path, and the string to look for. It
looks in a single file.

FORTH> look corewars.frt swap dup
  1    SWAP DUP @ 5 * SWAP CELL+            \ #bytes and start addr ok

When a full screen is displayed, these words wait for a key
press. Pressing Esc stops, others will continue displaying the
remaining text.

Needed file: LIB\SEARCHER.FRT


4.3 The referencer

To look up words in compiled code, you can use the referencer,
e.g.:

FORTH> ref cells
        DECOMPILER
TAB@
        EXTRA
RESTORE-SCREEN  RECOVER-SCREEN  SAVE-SCREEN  SAVE  FINDMESSAGE  >LOCAL  H,  L,
DOFORGET  DIAGNOSE
        FORTH
(VIEW)  2VARIABLE  VARIABLE
13 references of: $1008 CELLS found. ok

Needed file: LIB\REF.FRT


4.4 Help words glossary

(REF)              "paren-ref"                             REF
    ( addr -- )
    Find compiled references in colon definitions of addr in all word
    lists. Display the words where the references occur and the count
    of the words where the references are found.

ANY                                                        SEARCHER
    ( "ccc" -- )
    Skip leading space delimiters. Parse ccc delimited by a space.
    Search the files with extension given by HEXT$ in the directory
    given by HELPPATH . Display the description of the names that
    contain ccc. If a full screen is displayed, wait for the user to
    press a key. Stop if the key is the escape key.

HELP                                                       HELP
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Look up name in the files with extension given in HEXT$ in the
    directory given by HELPPATH and display the description of name.
    As a binary search on the sorted file is performed, only one
    descripition per file is displayed. When a full screen is
    displayed, wait for the user to press any key, escape stops.
    Otherwise convert name to a number (the prefixes % $ # & etc. are
    permitted) and display its type and decimal value and the
    character if it can be displayed or display the exception message
    if it is defined for the number.

LOOK                                                       SEARCHER
    ( "name" "ccc" --- )
    Skip leading space delimiters. Parse name delimited by a space.
    Skip leading SEPARATOR delimiters. Parse ccc delimited by
    SEPARATOR . Search file name with optional extension given by
    FEXT$ . Find ccc in the file. Display the number of the lines 
    found, the line number and the line containing ccc depending on
    the width of the screen. If a full screen is displayed, wait for
    the user to press a key. Stop if the key is the escape key.

REF                                                        REF
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Find compiled references in colon definitions of name in all word
    lists. Display the words where the references occur and the count
    of the words where the references are found.

SF                 "search-forth"                          SEARCHER
    ( "ccc" -- )
    Skip leading SEPARATOR delimiters. Parse ccc delimited by
    SEPARATOR . Search the files with extension given by FEXT$ in the
    current directory. Find ccc in the files. Display the number of
    lines found, the name of the file, the line number and the line
    depending on the width of the screen. If a full screen is
    displayed, wait for the user to press a key. Stop if the key is
    the escape key.

SL                 "search-libraries"                      SEARCHER
    ( "ccc" -- )
    Skip leading SEPARATOR delimiters. Parse ccc delimited by
    SEPARATOR . Search the files with extension given by FEXT$ in the
    directory given by LIBPATH . Find ccc in the files. Display the
    number of lines found, the name of the file, the line number and
    the line depending on the width of the screen. If a full screen
    is displayed, wait for the user to press a key. Stop if the key
    is the escape key.

The decompiler, disassembler and viewer are described elsewhere.

========================================
5. Local variables

Instead of creating definitions with complex stack uses, the
programmer can use variables. The problem with variables is that
they are not local to a definition and other words can use them
and may produce unwanted side-effects.

ANS Forth offers a way to use variables local to a definition
that are not known outside that definition. In this way the user
can give them names that do not conflict with global or other
local variables. A further improvement is that the use of a local
variable's name will give the value directly without @, like a
VALUE . To change the value, use TO , +TO or CLEAR.


5.1 Use of locals

The calculation of the discriminant in square roots is whithout
the use of local values:

: DISCRIMINANT      ( a b c -- d )      \ d=b*b-4*a*c
        SWAP                            \ a c b
        DUP *                           \ a c b*b
        -ROT                            \ b*b a c
        *                               \ b*b a*c
        4 *                             \ b*b 4*a*c
        -                               \ d
    ;

The standard ANS Forth way to use locals is as follows:

: DISCRIMINANT      ( a b c -- d )      \ d=b*b-4*a*c
        LOCALS| c b a |                 \ stack empty
        b b *                           \ b*b
        4 a * c *                       \ b*b 4*a*c
        -                               \ d
    ;

Rememer that at the start of the definition, the value on the top
of the stack will be placed in the first local value. The names
after the words LOCALS| are therefore in reverse order to the
stack diagram.

In CHForth the restriction that no operation is allowed between
declaring locals is not applicable (but the program will be
non-standard):

: DISCRIMINANT      ( a b c -- d )      \ d=b*b-4*a*c
        LOCAL c                         \ a b
        DUP *                           \ do some operation
        LOCAL b*b                       \ a
        c * -4 *                        \ -4*a*c
        b*b +                           \ d
    ;


5.2 Internals of local variables

When defining a local variable the pointers HERE and HHERE are
temporary changed to a special area that is also used by FLYER to
compile code and headers that will not interfere with the normal
compiling.

For every local variable the word PUSH-LOCAL is compiled that
transfers the value on the top of the stack to the local stack
and pushes the addres of special routine on the return stack. At
the end of the definition this routine is executed and it will
discard the storage area on the local stack and then return to
the calling definition with EXIT as normal.

When decompiling you will see that the first named local will be
called LOCAL 0 and the second LOCAL 1 and so on.

The word (LOCAL) can be used do make defining words for locals.
Try decompiling the definition of LOCAL or LOCALS| to see
examples for this.


5.3 More local types

Double locals and other types are defined in the file
LIB\DLOCALS.FRT and can be included by NEEDS -dlocals .


5.4 Local words glossary

(LOCAL)            "paren-local-paren"                     FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( c-addr u -- )
    When executed during compilation, (LOCAL) passes a message to
    the Forth system that has one of two meanings. If u is
    non-zero, the message identifies a new local whose word name
    is given by the string of characters identified by c-addr u.
    If u is zero, the message is 'last local' and c-addr has no
    significance. The result of executing (LOCAL) during
    compilation of a definition is to create a set of named local
    identifiers, each of which is a word name, that have execution
    semantics within the scope of that definition's source only.
    
    local Execution: ( -- x )
    Push the local's value, x, onto the stack. An ambiguous
    condition exists when (LOCAL) is executed while in interpret
    state.
    
    Note: This word is not intended for direct use in a definition
    to declare that definition's locals. It is instead used by
    system or user compiling words. These compiling words in turn
    define their own syntax, and may be used directly in
    definitions to declare locals.

+TO                "plus-to"                               EXTRA
    Interpretation: ( n|u "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Add n|u to name. Exception -32 occurs if name was not defined by
    VALUE or VARIABLE .
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -32 occurs if name was not defined by VALUE
    , VARIABLE or (LOCAL).
    
    Run-time: ( x -- )
    Add n|u to name.

CLEAR                                                      EXTRA
    Interpretation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Store zero in name. Exception -32 occurs if name was not defined
    by VALUE or VARIABLE .
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -32 occurs if name was not defined by VALUE
    , VARIABLE or (LOCAL).
    
    Run-time: ( -- )
    Store zero in name.

END-LOCAL                                                  EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( -- )
    Terminate creation of local values.

LOCAL                                                      EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a definition for name with the execution and run-time
    semantics defined below.
    
    Execution: ( x -- )
    Store x in name.
    
    name Execution: ( -- x )
    Place x on the stack. The value can be manipulated by TO +TO and
    CLEAR .

LOCAL-WORDLIST                                             ONLY
    ( -- wid )
    Return the wid of the LOCAL-WORDLIST .

LOCALS|            "locals-bar"                            FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "namen" .. "name2" "name1" "|" -- )
    Define up to 8 local variables with "name1" to "namen". The list
    of locals to be defined is terminated with "|". The actual number
    in CHForth may be greater, depending on the length of the input
    line. Append the run-time semantics for name given below.
    
    name Run-time: ( -- x )
    Place x on the stack. The value can be manipulated by TO +TO and
    CLEAR .

TO                                                         FORTH
    Interpretation: ( x "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Store x in name. Exception -32 occurs if name was not defined by
    VALUE or VARIABLE .
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -32 occurs if name was not defined by VALUE
    , VARIABLE or (LOCAL).
    
    Run-time: ( x -- )
    Store x in name.

========================================
6. Forget and forget fields

As Forth can be used as a development environment, sometimes the
user wants to get rid of old definitions and start new ones. The
words provided for this are the old word FORGET and the new word
MARKER .


6.1 FORGET

When FORGET followed by a name is typed in all definitions made
later than name and name itself are forgotten, the dictionary
pointer ( HERE ) is reset as all Forth versions do, but there is
a field in the header of each word that may contain the execution
token of a special routine. Every time FORGET is typed, it scans
the headers, starting with the newest word by using HIGHEST and
looks for the contents of this field and executes the token and
continues with the next word. This routine is entered with the
data field of the word found by HIGHEST on the stack and can
therefore perform some restoration action with that address. For
example when a word from type INTVEC is forgotten, it will
restore the former contents of the vector. A colon definition has
a forget routine that places the list dictionary pointer back to
what it was when the word was created. Remember that any word
that was in the dictionary when EXTEND was executed can not be
forgotten, and any word that was in the executable file when
CHForth was started, because SAVE contains EXTEND .


6.2 MARKER

The new method is MARKER . This is a defining word, it creates a
definition for the following name. When name is typed, everything
including name and later definitions are removed, this process is
the same if you typed: FORGET name. As a convention to remember
its action, a '-' (minus sign) is sometimes appended in front of
name. When name is executed, apart from the normal FORGET action,
the search order is restored to the point where MARKER was
executed, so you do not have to remember it yourself.


6.3 Examples

: ONE ;  : TWO ;  : THREE ;  : FOUR ;   \ some new definitions
FORGET THREE                            \ forget the last two
: FIVE ; : SIX ;                        \ and start other words

FORTH DEFINITIONS                       \ Set a starting order
MARKER -vergessen                       \ Set a marker
VIERTE DEFINITIONS                      \ Set new search order
: Eins ONE ; : Zwei TWO ; : Sechs SIX ;
FUENFTE DEFINITIONS                     \ Change order
-vergessen                              \ The last four are gone
ORDER                                   \ Will print FORTH as 1st

DOER: DOMESSAGE                         \ address of data field
        CR COUNT TYPE                   \ Print the message
    ;

: MESSAGE  CREATE [CHAR] " WORD C@      \ Define message definer
           CHAR+ ALLOT                  \ Compile the string
        DOMESSAGE
    ;

:NONAME  CR ." Forgetting message "     \ Print a forget message
        COUNT TYPE                      \ The same address as
    ;                                   \ after DOES>
    IS-FORGET DOMESSAGE                 \ Put in a MESSAGE type

MESSAGE MESS-1 This is message one"
MESSAGE MESS-2 This is message two"


6.4 Forget words glossary

FENCE                                                      EXTRA
    ( -- a-addr )
    a-addr is the adress of a cell containing the dictionary pointer
    since the last SAVE or EXTEND . Forgetting of words created when
    the dictionary pointer was less than this value is not possible.

FORGET                                                     FORTH
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Find name in the compilation word list, then delete name from the
    dictionary along with all words added to the dictionary after
    name. Exception -13 occurs if name cannot be found. Exception -15
    occurs if FORGET removes a word required for correct execution.
    
    Note: this word is obsolescent and is included as a concession to
    existing implementations.
    
    Note: In CHForth words can be protected against FORGET with
    EXTEND and SAVE .

HEAD>FORGET        "head-to-forget"                        EXTRA
    ( dea -- h-addr )
    h-addr is the forget field address of the dictionary entry dea.

HIGHEST                                                    EXTRA
    ( -- wid dea )
    Return the dictionary entry address of the newest definition with
    dictionary entry address dea and the word list identification wid
    in which it is compiled. Used in FORGET .

IS-FORGET                                                  EXTRA
    ( xt "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the semantics of execution token xt to the forget method
    of name.

MARKER                                                     FORTH
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a dictionary for name with the execution semantics defined
    below.
    
    name Executing: ( -- )
    Restore all dictionary allocation and search pointers to the
    state they had just prior to the definition of name. Remove the
    definition of name and all subsequent definitions. Restoration of
    any structures still existing that could refer to deleted
    definitions or deallocated data space is not necessarily
    provided. No other contextual information such as numeric base is
    affected.

========================================
7. Numbers and strings

Standard Forth has two types of numbers, single precision: in
CHForth signed numbers from -32768 to 32767 or unsigned from 0 to
65535, and double precision numbers (entered by one or more
decimal points in the number) from -2147483648 to 2147483647 or
from 0 to 4294967295. The only allowed prefix is the minus sign.


7.1 Numbers

Numbers in other bases than decimal ten are in Standard Forth
only possible if you change BASE before the number and restore it
afterwards. In CHForth (and other Forths as well) this is solved
by prefixing the number by special characters as follows:
    '#' for decimal numbers, digits 0..9,
    '$' for hexadecimal numbers, digits 0..9 and A..F,
    '%' for binary numbers, digits 0 and 1.
The minus sign if present must be after this prefix.


7.2 Characters

Characters are in Standard Forth entered by placing the word CHAR
(when interpreting) or [CHAR] (when compiling) and a space before
the character. In CHForth this is extended by prefixes. Placing a
'&' character without a space before a single character places
this number on the stack while interpreting or compiles it as a
literal. It is also possible to place a ''' character just before
and just after the desired character.

Control characters are entered by placing the word CTRL (when
interpreting) or [CTRL] (when compiling) and a space before an
uppercase character which is converted to is value between 0 and
31. An other way is placing a '^' character without a space
before a single character.


7.3 Strings

Strings in Forth come in two varieties, the first and oldest
species is the counted string. On the stack is an address. On
that address is a byte containing the size of the string right
after that byte. The length of the string is between 0 and 255
both inclusive. It is used by words as WORD and FIND and
converted to the new type by COUNT .

The newer version has an address and a length on the stack, this
length can be from zero to 65535, practically infinite. These are
handled by other words that expect a string on the stack. But it
is not generally possible to convert such a string to a member of
the old type as this type of strings is often not preceded by a
count byte and sometimes the length is larger than 255.

CHForth provides some operators to store and concatenate strings.
PACK and PLACE put a c-addr u string on an address as a counted
string and PACK leaves this address on the stack and PLACE does
not. APPEND places a c-addr u string at the end of a counted
string and corrects the size of the compound string. APPEND-CHAR
appends a character to a counted string and increments the count
of the string with one.


7.4 Numbers and strings word glossary

",                 "quote-comma"                           EXTRA
    ( "ccc<">" -- )
    Parse ccc delimited by '"' (double quote) and compile it as a
    counted string in the dictionary. Execution of HERE just before
    the execution of ", will give the address of the string.

#                  "number-sign"                           FORTH
    ( ud1 -- ud2 )
    Divide ud1 by the number in BASE giving the quotient ud2 and the
    remainder n. (n is the least-significant digit of ud1). Convert n
    to external form and add the resulting character to the beginning
    of the pictured numeric output string. An ambiguous condition
    exists if # executes outside of a <# #> delimited number
    conversion.
    See also: #> #S <#

#>                 "number-sign-greater"                   FORTH
    ( xd -- c-addr u )
    Drop xd. Make the pictured numeric output string available as a
    character string. c-addr and u specify the resulting character
    string. A Standard Program may replace characters within the
    string.
    See also: # #S <#

#S                 "number-sign-s"                         FORTH
    ( ud1 -- ud2 )
    Convert one digit of ud1 according to the rule for # . Continue
    conversion until the quotient is zero. An ambiguous condition
    exists if #S executes outside of a <# #> delimited number
    conversion.
    See also: # #> <#

(.)                "paren-dot"                             EXTRA
    ( n -- c-addr u )
    Convert n to a numeric output string with a leading minus sign if
    n is negative.

(D.)               "paren-d-dot"                           EXTRA
    ( d -- c-addr u )
    Convert d to a numeric output string with a leading minus sign if
    d is negative.

(NUMBER?)          "paren-number-question"                 EXTRA
    ( c-addr u -- 0 | n 1 | d 2 )
    Convert a string to a number. If it fails, return a false flag.
    Otherwise return a single number with a flag of 1 and a double
    number with a flag of 2. The number is negative if prefixed by
    '-'. CHForth allows decimal numbers to be prefixed by '#' ,
    hexadecimal numbers by '$' and binary numbers by '%' . These may
    be followed by '-' to signify negative numbers. Single characters
    are converted to single precision number when prefixed by '&' or
    when they are enclosed by '''. Uppercase letters can be converted
    to the corresponding control characters when prefixed by '^'.

-TRAILING          "dash-trailing"                         FORTH
    ( c-addr u1 -- c-addr u2 )
    If u1 is greater than zero, u2 is equal to u1 less the number of
    spaces at the end of the character string specified by c-addr u1.
    If u1 is zero or the entire string consists of spaces, u2 is
    zero.

.                  "dot"                                   FORTH
    ( n -- )
    Display n in free field format.

.DEC               "dot-decimal"                           EXTRA
    ( n -- )
    Display n as a signed decimal number.
    See also: .HEX

.HEX               "dot-hex"                               EXTRA
    ( u -- )
    Display u as a four digit hexadecimal number with a leading '$'
    character and a trailing space.
    See also: .DEC H.

.R                 "dot-r"                                 FORTH
    ( n1 n2 -- )
    Display n1 right aligned in a field n2 characters wide. If the
    number of characters required to display n2 is greater than n2,
    all digits are displayed with no leading spaces in a field as
    wide as necessary.

.S                 "dot-s"                                 FORTH
    ( -- )
    Copy and display the values currently on the data stack. Starting
    on a new line, a '(' (left parenthesis) followed by a space is
    displayed. Then follow the values on the stack, when BASE
    contains 10, as signed numbers, unsigned otherwise. At the end a
    ')' (right parenthesis) is displayed.
    
    .S is implemented using pictured numeric output words. Its use
    will corrupt the transient region identified by #> .

.SEG               "dot-segment"                           EXTRA
    ( u -- )
    Display u as a four character string if it corresponds to a
    segment in CHForth else as a four digit hexadecimal string.

/STRING            "slash-string"                          FORTH
    ( c-addr1 u1 n -- c-addr2 u2 )
    Adjust the character string at c-addr1 by n characters. The
    resulting character string, specified by c-addr2 u2, begins at
    c-addr1 plus n characters and is u1 minus n characters long.

2LITERAL           "two-literal"                           FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( x1 x2 -- )
    Append the run-time semantics defined below to the current
    definition.
    
    Run-time: ( -- x1 x2 )
    Place cell pair x1 x2 on the stack.

<#                 "less-number-sign"                      FORTH
    ( -- )
    Initialize the pictured numeric output conversion process.
    See also: # #> #S

><                 "flip"                                  EXTRA
    ( x1 -- x2 )
    See: FLIP

>NUMBER            "to-number"                             FORTH
    ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )
    ud2 is the unsigned result of converting the characters within
    the string specified by c-addr1 u1 into digits, using the number
    in BASE , and adding each into ud1 after multiplying ud1 by the
    number in BASE . Conversion continues left-to-right until a
    character that is not convertible, including any "+" or "-" is
    encountered or the string is entirely converted. c-addr2 is the
    location of the first unconverted character or the first
    character past the end of the string if the string was entirely
    converted. u2 is the number of unconverted characters in the
    string. An ambiguous condition exists if ud2 overflows during the
    conversion.

>UPC               "to-u-p-c"                              EXTRA
    ( char1 -- char2 )
    Convert char1 to uppercase.

?                  "question"                              FORTH
    ( a-addr -- )
    Display the value stored at a-addr.

APPEND                                                     EXTRA
    ( c-addr1 u c-addr2 -- )
    Add u to the numerical value of the character at c-addr2. Store
    the string specified by c-addr1 u at the character address given
    by the sum of c-addr2 and the incremented numerical value of the
    character at c-addr2.

APPEND-CHAR                                                EXTRA
    ( char c-addr -- )
    Increment the numerical value of the character at c-addr by one.
    Store char at the character address given by the sum of the
    incremented numerical value of the character at c-addr and
    c-addr.

B.                 "b-dot"                                 EXTRA
    ( u -- )
    Display u as a two digit hexadecimal number with a trailing
    space.
    See also: H.

BASE                                                       FORTH
    ( -- a-addr )
    a-addr is the address of a cell containing the current number
    conversion radix {{2..36}}.

BL                 "b-l"                                   FORTH
    ( -- char )
    char is the character value for a space.

C"                 "c-quote"                               FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "ccc<quote>" -- )
    Parse ccc delimited by " (double-quote). Append the run-time
    semantics given below to the current definition.
    
    Run-time: ( -- c-addr )
    Return c-addr, a counted string consisting of the characters ccc.
    A standard program shall not alter the returned string.
    See also: S"

CHAR               "char"                                  FORTH
    ( "name" -- char )
    Skip leading space delimiters, Parse name delimited by a space.
    Put the value of its first character on the stack.
    See also: [CHAR]

CMOVE              "c-move"                                FORTH
    ( c-addr1 c-addr2 u -- )
    If u is greater than zero, copy u consecutive characters,
    character-by-character and left-to-right, from c-addr1 to
    c-addr2. If c-addr2 lies within the source region, memory
    propagation occurs. (c-addr2 lies within the source region if
    c-addr2 is not less than c-addr1 and c-addr2 is less than the
    quantity c-addr1 u CHARS + ).
    See also: CMOVE> MOVE

CMOVE>             "c-move-up"                             FORTH
    ( c-addr1 c-addr2 u -- )
    If u is greater than zero, copy u consecutive characters,
    character-by-character and right-to-left, from c-addr1 to
    c-addr2. If c-addr1 lies within the destination region, memory
    propagation occurs. (c-addr1 lies within the destination region
    if c-addr1 is greater than or equal to c-addr2 and if c-addr2 is
    less than the quantity c-addr1 u CHARS + ).
    See also: CMOVE MOVE 

CMOVEX             "c-move-x"                              EXTRA
    ( x-addr1 x-addr2 u -- )
    If u is greater than zero, copy u consecutive characters,
    character-by-character and left-to-right, from extended address
    x-addr1 to extended address x-addr2. If x-addr2 lies within the
    source region, memory propagation occurs. (x-addr2 lies within
    the source region if x-addr2 is not less than x-addr1 and x-addr2
    is less than the quantity x-addr1 u CHARS + ).
    See also: CMOVE CMOVEX>

CMOVEX>            "c-move-x-up"                           EXTRA
    ( x-addr1 x-addr2 u -- )
    If u is greater than zero, copy u consecutive characters,
    character-by-character and right-to-left, from extended address
    x-addr1 to extended address x-addr2. If x-addr2 lies within the
    source region, memory propagation occurs. (x-addr2 lies within
    the source region if x-addr2 is not less than x-addr1 and x-addr2
    is less than the quantity x-addr1 u CHARS + ).
    See also: CMOVE CMOVEX

COMPARE                                                    FORTH
    ( c-addr1 u1 c-addr2 u2 -- flag )
    Compare the string specified by c-addr1 u2 to the string
    specified by c-addr2 u2. The strings are compared, beginning at
    the given addresses, character by character, up to the length of
    the shorter string or until a difference is found. If the two
    strings are identical up to the length of the shorter string, n
    is zero if both strings are of equal length, minus-one of u1 is
    less than u2, and one otherwise. If the two strings are not
    identical up to the length of the shorter string, n is minus-one
    if the first non-matching character in the string specified by
    c-addr1 u1 has a lesser numerical value than the corresponding
    character in the string specified by c-addr2 u2 and one
    otherwise.
    See also: COMPARE-UPPERCASE

COMPARE-UPPERCASE                                          EXTRA
    ( c-addr1 u1 c-addr2 u2 -- flag )
    Compare the string specified by c-addr1 u2 to the string
    specified by c-addr2 u2. The strings are compared, beginning at
    the given addresses, character by character, up to the length of
    the shorter string or until a difference is found. If the two
    strings are identical, where lower case characters are considered
    equal to upper case characters, up to the length of the shorter
    string, n is zero if both strings are of equal length, minus-one
    of u1 is less than u2, and one otherwise. If the two strings are
    not identical up to the length of the shorter string, n is
    minus-one if the first non-matching character in the string
    specified by c-addr1 u1 has a lesser numerical value, where the
    value of lower case characters are converted to their upper case
    equivalent values without affecting the strings themselves, than
    the corresponding character in the string specified by c-addr2 u2
    and one otherwise.
    See also: COMPARE

CONVERT                                                    OBSOLETE
    ( ud1 c-addr1 -- ud2 c-addr2 )
    ud2 is the result of converting the characters within the text
    beginning at the first character after c-addr1 into digits,
    using the number in BASE , and adding each digit to ud1 after
    multiplying by the number in BASE . Conversion continues until
    a character that is not convertible is encountered. c-addr2 is
    the location of the first unconverted character. An ambiguous
    condition exists if ud2 overflows.
    
    Note: this word is obsolescent and is included as a concession
    to existing implementations. Its function is superseded by
    >NUMBER .

COUNT                                                      FORTH
    ( c-addr1 -- c-addr2 char )
    Return the character string specification for the counted string
    stored at c-addr1. c-addr2 is the address of the first character
    after c-addr1. u is the contents of the character at c-addr1,
    which is the length in characters of the string at c-addr2.

COUNTX             "count-x"                               EXTRA
    ( x-addr1 -- x-addr2 char )
    Fetch char from extended address x-addr1 and add 1 CHARS to
    x-addr1 giving x-addr2.

CTRL               "control"                               EXTRA
    ( "name" -- char )
    Skip leading space delimiters, Parse name delimited by a space.
    Put the value of the control character defined by its first
    character on the stack. Exception -531 occurs when the character
    is not in the range {'@'..'_'}.
    See also: CHAR [CTRL]

D.                 "d-dot"                                 FORTH
    ( d -- )
    Display d in free field format.

D.R                "d-dot-r"                               FORTH
    ( d n -- )
    Display d right aligned in a field n characters wide. If the
    number of characters required to display d is greater than n, all
    digits are displayed with no leading spaces in a field as wide as
    necessary.

DECIMAL                                                    FORTH
    ( -- )
    Set the numeric conversion radix to ten (decimal).

DIGIT                                                      EXTRA
    ( char +n -- n1 true | char false )
    Try to convert char to a digit n1 with number base +n. If the
    conversion succeeds, return a true flag. Otherwise a false flag.

DPL                "d-p-l"                                 EXTRA
    ( -- a-addr )
    a-addr is the address of a cell. When the last interpreted number
    contained a decimal point, it will contain the number of digits
    after the decimal point in that number; otherwise the contents
    are -1.

EXPAND                                                     EXTRA
    ( c-addr1 u1 c-addr2 -- c-addr2 u2 )
    Copy any non-tab characters in the string specified by c-addr u1
    to a string specified by c-addr2 u2. Tab characters are expanded
    to spaces with a tab distance of 8 positions.

FLIP                                                       EXTRA
    ( x1 -- x2 )
    Exchange the high and low bytes of x1 giving x2.

H.                 "h-dot"                                 EXTRA
    ( u -- )
    Display u as a four digit hexadecimal number with a trailing
    space.
    See also: .HEX B.

HEX                                                        FORTH
    ( -- )
    Set the contents of BASE to sixteen.

HOLD                                                       FORTH
    ( char -- )
    Add char to the beginning of the pictured numeric output string.
    An ambiguous condition exists if HOLD executes outside of a <# #>
    delimited number conversion.

INLINE#            "inline-number"                         EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    ( -- x )
    Return the inline compiled number, system use only.

INLINE$            "inline-string"                         EXTRA
    ( -- l-addr )
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    l-addr is the list address of an inline compiled string. System
    use only.

JOIN                                                       EXTRA
    ( char1 char2 -- x )
    char1 is the low byte of x and char2 is the high byte of x.

KB.                "k-b-dot"                               EXTRA
    ( u -- )
    Display the result of division of u by 1024 with one digit after
    the decimal point followed by a space, the string "Kb" and a
    space.

LITERAL                                                    FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( x -- )
    Compile x as a literal. Append the run-time syntax given below
    to the current definition.
    
    Run-time: ( -- x )
    Place x on the stack.

LITERALS                                                   EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( x1 .. xn n -- )
    Append the execution semantics defined below to the current
    definition.
    
    Executing:
    ( -- x1 .. xn )
    Place x1 to xn on the stack.

NUMBER?            "number-question"                       EXTRA
    ( c-addr u -- 0 | n 1 | d 2 )
    A word that normally executes (NUMBER?) .

PACK                                                       EXTRA
    ( c-addr1 u c-addr2 -- c-addr2 )
    Place the string specified by c-addr1 u as a counted string at
    c-addr2.

PAD                                                        FORTH
    ( -- c-addr )
    c-addr is the address of a transient region that can be used to
    hold data for intermediate processing.

PLACE                                                      EXTRA
    ( c-addr1 u c-addr2 -- )
    Place the string specified by c-addr1 u as a counted string at
    c-addr2.

S"                 "s-quote"                               FORTH
    Interpretation: ( "ccc<quote>" -- c-addr u )
    Parse ccc delimited by " (double quote). Store the resulting
    string ccc at a temporary location. The maximum length of the
    temporary buffer is 255 characters. CHForth allows for the
    storing of more such strings before new strings start to
    overwrite the buffer. A standard program shall not alter the
    returned string.
    
    Compilation: ( "ccc<quote>" -- )
    Parse ccc delimited by " (double quote). Append the run-time
    semantics given below to the current definition.
    
    Run-time: ( -- c-addr u )
    Return c-addr and u describing a string consisting of the
    characters ccc. A standard program shall not alter the returned
    string.
    See also: C"

SCAN                                                       EXTRA
    ( c-addr1 u1 char -- c-addr2 u2 )
    Scan the string specified by c-addr1 u1 for an occurence of char
    and return the part of the string starting with the found char as
    a string specified by c-addr2 u2. If the string specified by
    c-addr1 u1 does not contain char, u2 is zero.
    
    If char is the character for space, control characters are
    considered equal to char.

SEARCH                                                     FORTH
    ( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag )
    Search the string specified by c-addr1 u1 for the string
    specified by c-addr2 u2. If flag is true, a match was found at
    c-addr3 with u3 characters remaining. If flag is false there was
    no match and c-addr3 is c-addr1 and u3 is u1. 

SIGN                                                       FORTH
    ( n -- )
    If n is negative, add a minus sign to the beginning of the
    pictured numeric output string. An ambiguous condition exists if
    SIGN executes outside of a <# #> delimited number conversion.

SKIP                                                       EXTRA
    ( c-addr1 u1 char -- c-addr2 u2 )
    Skip leading occurences of char in the string specified by
    c-addr1 u1 and return the remaining string specified by c-addr2
    u2. If the string specified by c-addr1 u1 contains only
    occurences of char, u2 is zero.
    
    If char is the character for space, control characters are
    considered equal to char.

SLITERAL                                                   FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( c-addr1 u -- )
    Append the run-time semantics given below to the current
    definition.
    
    Run-time: ( -- c-addr2 u )
    Return c-addr2 u describing a string consisting of the characters
    specified by c-addr1 u during compilation. A Standard Program
    shall not alter the returned string.

SPLIT                                                      EXTRA
    ( x -- char1 char2 )
    char1 is the low byte of x and char2 is the high byte of x.

SRCSEG             "source-segment"                        EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing the segment address of
    the first string in COMPARE and SEARCH . The user is reponsible
    to restore the default value ( CSEG ) after using an alternative
    value in COMPARE and SEARCH .

STYPE              "s-type"                                EXTRA
    ( c-addr u -- )
    If u is greater than zero, display the character string specified
    by c-addr and u. The characters are displayed as with SEMIT .

STYPEX             "s-type-x"                              EXTRA
    ( x-addr u -- )
    If u is greater than zero, display the character string at the
    extended address x-addr for a total of u characters. The
    characters are displayed as with SEMIT .

TYPE                                                       FORTH
    ( c-addr u -- )
    If u is greater than zero, display the character string specified
    by c-addr and u.
    See also: EMIT

TYPEX              "type-x"                                EXTRA
    ( x-addr u -- )
    If u is greater than zero, display the character string at the
    extended address x-addr for a total of u characters.

TYPEZ              "type-z"                                EXTRA
    ( x-addr -- )
    While the character at the extended address x-addr is not zero,
    display the character and increment x-addr.

U.                 "u-dot"                                 FORTH
    ( u -- )
    Display u in free field format.

U.R                "u-dot-r"                               FORTH
    ( u n -- )
    Display u right aligned in a field n characters wide. If the
    number of characters required to display u is greater than n, all
    digits are displayed with no leading spaces in a field as wide as
    necessary.

UD.                "u-d-dot"                               EXTRA
    ( ud -- )
    Display ud in free field format.

UD.R               "u-d-dot-r"                             EXTRA
    ( ud n -- )
    Display ud right aligned in a field n characters wide. If the
    number of characters required to display ud is greater than n,
    all digits are displayed with no leading spaces in a field as
    wide as necessary.

UPPER                                                      EXTRA
    ( c-addr u -- )
    Convert the lowercase characters in the string specified by
    c-addr u to uppercase.

[CHAR]             "bracket-char"                          FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition.
    
    Run-time: ( -- char )
    Place char char, the value of the first character of name, on the
    stack.
    See also: CHAR

[CTRL]             "bracket-control"                       EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -531 occurs when the character is not in
    the range {'@'..'_'}.
    
    Run-time: ( -- char )
    Place char, the value of the first character of name, after
    conversion to a control character, on the stack.
    See also: CTRL [CHAR]

========================================
8. Word lists


Word lists in Forth are a method to group words with specific
semantics. Also the search time is reduced when internal words
are places in word list that are currently not accessible.


8.1 WORDLIST and VOCABULARY

The Standard way to create a word list is by the word WORDLIST
that creates an initially empty list and returns its word list
identification (wid), in CHForth its address. This is the base
for a more convenient word, VOCABULARY that gives a name to this
list. When executed, the vocabulary replaces the wid in the
search order. The wid can be obtained by placing GET for a word
defined by WORDLIST .


8.2 Search order

The search order is another list. When FIND and ' search for
name, they take every wid in the search order, starting from the
top, and look in the word list for name. They are ready when name
matches a name in a word list. It therefore possible to have more
words of the same name in different word lists with a different
semantics provided the right word is in a word list that is
searched earlier. The search order can be set by SET-ORDER and is
returned by GET-ORDER . The search order can be extended by ALSO
and diminished by PREVIOUS . The list where the compiled words
are places is set by SET-CURRENT or DEFINITIONS . The first word
list in the order can be set and reset by SET-CONTEXT and
GET-CONTEXT respectively.


8.3 CHForth word lists

All Standard words except some that are in ONLY are placed in
FORTH . Most extensions are found in EXTRA . In INTERNAL are the
words that are not documented and are internally to the system.
In EDITOR are the words for ACCEPT and in ASSEMBLER DECOMPILER
and DISASSEMBLER are still more words that are used in their
specific environment. -1 SET-ORDER will place the ONLY word list
in the first and second place of the search order and the count
to two. -2 SET-ORDER (not Standard) will extend this with EXTRA
and FORTH on the top. The wid returned by GET-CURRENT is not
changed.


8.4 Example

CHForth offers a method to find words in a word list that have
special properties. For example when you want to know what words
are immediate, use this:

INTERNAL DEFINITIONS                    \ (IMMED) is internal

ALSO FORTH                              \ New search order

: (IMMED)       ( wid -- )
        DUP BODY> >HEAD ?DUP            \ Has word list a name?
        IF      CR 8 SPACES .HEAD       \ Display it on a new line
        THEN
        CR VOC@ TEMPORARY !             \ Store wid, required for
        BEGIN   ANOTHER                 \    ANOTHER gives a flag
        WHILE   DUP HEAD>FLAGS H@       \    and a dea, check flags
                =IMMEDIATE AND          \ Is word immediate
                IF      ?HEAD           \ Display in 16 char column
                ELSE    DROP            \ Not immediate
                THEN
        REPEAT
    ;

DEFINITIONS                             \ .IMMEDIATE is FORTH

: .IMMEDIATE    ( -- )
        EVERY?                          \ Typed EVERY before?
        IF      VOC-LINK                \ All word lists
                BEGIN   REGULAR?        \ Only VOCABULARIES
                        IF      DUP (IMMED) \ Do internal word
                        THEN
                        @ ?DUP 0=       \ Every wid done
                UNTIL
        ELSE    GET-CONTEXT (IMMED)     \ Only the first in order
        THEN
    ;

PREVIOUS FORTH                          \ Old search order


8.5 Word list glossary

.VOCNAME           "dot-vocname"                           EXTRA
    ( wid -- )
    Display the name of the word list identification wid.
    See also: .HEAD

.WORDLISTS                                                 EXTRA
    ( -- )
    Display the word lists that have a name, those who have been
    created with VOCABULARY .

ALSO                                                       ONLY
    ( -- )
    Transform the search order consisting of wid1 .. widn-1 widn
    (where widn is searched first) into wid1 .. widn-1 widn widn.
    An ambiguous condition exists if there are too many word lists
    in the search order.

ANOTHER                                                    EXTRA
    ( -- dea true | false )
    Return the next dea in the word list. Used in words as WORDS .
    This word depends on the stored wid at TEMPORARY . When ANSI
    does not contain zero, only words marked with ANS are
    returned.

ASSEMBLER                                                  ASSEMBLER
    ( -- )
    Replace the first word list in the search order with the
    ASSEMBLER word list.

DECOMPILER                                                 DECOMPILER
    ( -- )
    Replace the first word list in the search order with the
    DECOMPILER word list.

DEFINITIONS                                                ONLY
    ( -- )
    Make the compilation word list the same as the first word list
    in the search order. Specifies that the names of subsequent
    definitions will be placed in the compilation word list.
    Subsequent changes in the search order will not effect the
    compilation word list.

DISASSEMBLER                                               DISASSEMBLER
    ( -- )
    Replace the first word list in the search order with the
    DISASSEMBLER word list.

EDITOR                                                     ONLY
    ( -- )
    Make the EDITOR word list the first word list to be searched.
    This word list contains CHForth specific extensions to the ANSI
    standard for the line input editor and the block editor. Note
    that these words are non-standard.

EXTRA                                                      ONLY
    ( -- )
    Make the EXTRA word list the first word list to be searched.
    This word list contains all CHForth specific extensions to the
    ANSI standard. Note that these words are non-standard.

FIND                                                       FORTH
    ( c-addr -- c-addr 0 | xt 1 | xt -1 )
    Find the Forth word named in the counted string at c-addr. If the
    word is not found after searching all word list in the search
    order, return c-addr and zero. If the definition is found, return
    xt. If the definition is immediate, also return 1, otherwise
    return -1.
    See also: ' ['] POSTPONE

FORTH                                                      FORTH
    ( -- )
    Make the FORTH word list the first word list to be searched. Note
    that this word list contains at startup only ANSI-standard words.

FORTH-WORDLIST                                             ONLY
    ( -- wid )
    Return wid, the identifier of the word list that includes all
    standard words provided by the implementation. This word list is
    initially the compilation word list and is part of the initial
    search order.

GET                                                        EXTRA
    ( "name" -- )
    Interpretation: ( "name" -- wid )
    Skip leading space delimiters. Parse name delimited by a space.
    wid is the word list identification associated with name.
    Exception -32 occurs if name was not defined by VOCABULARY .
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -32 occurs if name was not defined by
    VOCABULARY .
    
    Run-time: ( -- wid )
    wid is the word list identification associated with name.

GET-CONTEXT                                                ONLY
    ( -- wid )
    Return wid, the identifier of the first word list in the
    search order.

GET-CURRENT                                                ONLY
    ( -- wid )
    Return wid, the identifier of the compilation word list.

GET-ORDER                                                  ONLY
    ( -- wid1 .. widn n )
    Returns the number of word lists n in the search order and the
    word list identifiers wid1 .. widn identifying these word
    lists. widn identifies the word list searched first, and wid1
    the word list that is searched last. The search order is
    unaffected.

INTERNAL                                                   ONLY
    ( -- )
    Make the INTERNAL word list the first word list to be searched.
    This word list contains CHForth specific extensions to the ANSI
    standard that are not documented and can be changed by the author
    by name or action without prior consent. Note that these words
    are non-standard.

ORDER                                                      FORTH
    ( -- )
    Display the word lists in the search order in their search order
    sequence, from the first searched to the last searched. Also
    display the word list into which new definitions will be placed.
    
    ORDER is implemented using pictured numeric output words. Its use
    will corrupt the transient region identified by #> .

REGULAR?           "regular-query"                         EXTRA
    ( wid -- wid flag )
    If the word list identification wid has a header (when it was
    created with VOCABULARY ), return a true flag else a false flag.

SEARCH-CONTEXT                                             EXTRA
    ( c-addr u -- 0 | xt 1 | xt -1 )
    Find the Forth word specified by the character string c-addr u in
    all word lists in the search order, including LOCAL-WORDLIST when
    STATE does not contain zero and there are local values. Return
    the execution token and 1 if the word is IMMEDIATE and -1
    otherwise. If name can not be found, return a false flag. The
    name is internally converted to uppercase if the variable
    CASESENSITIVE is false.

SEARCH-WORDLIST                                            FORTH
    ( c-addr u wid -- 0 | xt 1 | xt -1 )
    Find the Forth word identified by the string c-addr u in the word
    list identified by wid. If the word is not found, return zero. If
    the word is found, return its execution token xt and 1 if the
    word is immediate, -1 otherwise.

SET-CONTEXT                                                ONLY
    ( wid -- )
    Set the first searched word list in the search order to the
    word list identified by wid.

SET-CURRENT                                                ONLY
    ( wid -- )
    Set the compilation word list to the word list identified by
    wid.

SET-ORDER                                                  ONLY
    ( wid1 .. widn n -- )
    Set the search order to the word lists wid1 .. widn.
    Subsequently, word list widn will be searched first, followed
    by word list widn-1 and so on, with word list wid1 searched
    last. If n is zero, empty the search order. If n is minus one,
    set the search order to the minimum search order wid(ONLY)
    wid(ONLY). When n is minus two, set the search order to
    wid(ONLY) wid(EXTRA) wid(FORTH) wid(FORTH). The maximum of n
    in this implementation is sixteen.

VOC!                                                       FORTH
    ( dea wid -- )
    Store the dictionary entry address dea in the word list described
    by the word list identifier wid.

VOC-LINK                                                   EXTRA
    ( -- x )
    A value that links all word lists and vocabularies.

VOC@                                                       EXTRA
    ( wid -- dea )
    Fetch the dictionary entry address dea of the last definition
    from the word list described by the word list identifier wid.

VOCABULARY                                                 EXTRA
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a definition for name with the execution semantics defined
    below. Create a new word list and store the word list identifier
    with the definition for name. name is referred to as a
    "vocabulary".
    
    name Execution: ( -- )
    Make the above created word list the current word list.

WORDLIST                                                   FORTH
    ( -- wid )
    **** Wat wordt er bedoeld met dynamisch ?
    Creates a new empty word list, returning its word list identifier
    wid. The new word list is dynamically allocated in data space.
    Note that other ANS systems may create the new word list in
    another place.

WORDS                                                      ONLY
    ( -- )
    List the word names in the first word list of the search order in
    colums of 16 characters wide and a count at the end.
    
    WORDS is implemented using pictured numeric output words. Its use
    will corrupt the transient region identified by #> .
    See also: EVERY

WORDSPEED                                                  EXTRA
    ( -- addr )
    a-addr is the address of a cell containing the delay after WORDS
    SEE DIS etc. in millseconds.

========================================
9. Vectors

Sometimes some words may require different actions in different
situations. CHForth offers a type of word, called a vector. These
vectors can be changed and new actions may be appended to the
normal action of it.


9.1 Vectors used by the system

KEY and EMIT are for character input and output.

COLD interprets the command line and jumps then to QUIT .

DIAGNOSE will display some information about the compiled memory
sizes and the time it took, only when someting is given on the
command line.

START does some work before COLD is started, can be CHAINed to
some other initializing word.

ATEXIT does some work before the program is stopped, like closing
an open log file and resetting used interrupt vectors.

'INTERPRET 'COMPILE and NUMBER? have the actions for interpreting
and compiling words and numbers in them for INTERPRET .

PROMPT may be changed.

BEEP will not probably change.

PAUSE is in EKEY . Put a word there and Forth will do this every
time it waits for a key press.


9.2 Examples

    : (BEEP)    7 EMIT ;        \ Sound the speaker long and hard
    VECTOR BEEP                 \ No action attached yet
    ' (BEEP) IS BEEP            \ Store the action
    BEEP                        \ A sound will be heard
    : (TONE)    100 440 TONE ;  \ More pleasant
    ' (TONE) IS BEEP            \ Another sound
    BEEP                        \ A new sound
    : (TONE2)
            CHAIN BEEP          \ Inherit the current action: (BEEP)
            100 MS              \ Wait a while
            (BEEP) ;            \ Old sound
    ' (TONE2) IS BEEP           \ New action appended
    BEEP                        \ Two tones

    ' BEEP IS PAUSE             \ A very irritating sound
    ' NOOP IS PAUSE             \ Do this to stop the above


9.3 Vector words glossary

CHAIN                                                      EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the current execution semantics of name to the current
    definition. Exception -32 occurs if name was not defined by
    VECTOR .

IS                                                         EXTRA
    Interpretation: ( xt "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Store execution token xt in name. Exception -32 occurs if name
    was not defined by VECTOR .
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -32 occurs if name was not defined by
    VECTOR .
    
    Run-time: ( xt -- )
    Store execution token xt in name.

POP                                                        EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -32 occurs if name was not defined by VALUE
    , VARIABLE or VECTOR .
    
    Run-time: ( -- ) ( R: x -- )
    Pop x associated with name from the return stack.

PUSH                                                       EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Append the run-time semantics given below to the current
    definition. Exception -32 occurs if name was not defined by VALUE
    , VARIABLE or VECTOR .
    
    Run-time: ( -- ) ( R: -- x )
    Push x associated with name on the return stack.

VECTOR                                                     EXTRA
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a definition for name with the execution semantics defined
    below. name is referred to as a "vector".
    
    name Execution: ( i*x -- j*x )
    Execute the execution token stored in the entry. The execution
    token can be manipulated by IS . Exception -525 occurs if no
    execution token is assigned to name.
    See also CHAIN POP PUSH

========================================
10. Interpreter structure

The interpreter is the interface between the user and the Forth
program. QUIT asks the user to input a line of text and the
interpreter parses words delimited by spaces and executes them,
or it will compile them in the dictionary when STATE is not zero.


10.1 QUIT

When after a cold start and perhaps interpreting the contents of
the command line, QUIT resets the stacks, displays the status
line and displays the prompt on a new line. This prompt will
display the name of the first word list in the search order.
Because I like to have a explicit prompt, this differs from the
Standard where only a flashing cursor is allowed, this can be
done by: ' NOOP IS PROMPT Then QUIT waits for input. When the
input is followed with a press on the enter key, the word
INTERPRET is executed by CATCH .  When all went right, the
message 'ok' will be displayed when STATE is zero and nothing
when it is not. Then the prompt will be displayed and the cycle
is complete. When CATCH received a number different from zero,
the appropriate error message is displayed and QUIT is reentered.


10.2 INTERPRET

INTERPRET parses a space delimited word and when STATE is zero,
the parsed word is passed to 'INTERPRET else to 'COMPILE . When
these have completed, the stacks are checked for over- and
underflow and the process is repeated. When an exception occurs
in 'INTERPRET or 'COMPILE the control is passed to the CATCH in
QUIT .


10.3 'INTERPRET

'INTERPRET is a VECTOR and contains $INTERPRET that searches the
words in the search order for a match with the name string it
gets from INTERPRET . It tries to find the name in the word lists
present in the search order and when the found word is not
compile-only its execution token will be executed otherwise -14
is THROWn to the CATCH in QUIT . When name can not be found, it
tries to convert the string to a number and puts the single or
double number on the stack otherwise -13 is THROWn.

When the variable ANSI is not zero, words that do not have the
ANS bit set in their headers will give a message just before
their execution and numbers that have non-standard prefixes will
also display this message.


10.4 'COMPILE

'COMPILE is a VECTOR and contains $COMPILE that searches the
words in the search order for a match with the name string it
gets from INTERPRET . It tries to find the name in the word lists
present in the search order and when the found word is immediate
its execution token will be executed otherwise its execution
token is compiled in the list segment. When name can not be
found, it tries to convert the string to a number and compiles
the single or double number in the list segment. When the
conversion to a number fails, message -518 is displayed and the
name is compiled as a S" string and the word FORWARD is compiled
after it.

When the variable ANSI is not zero, words that do not have the
ANS bit set in their headers will give a message just before
their execution or compilation and numbers that have non-standard
prefixes will also display this message.

The strings compiled when message -518 is given are executed by
FORWARD , an alias for EVALUATE , when the word in which the
string is compiled, so this  can be used as a primitive form as
forward referencing. This is not recommended, is main purpose is
to continue compiling when a word during compilation can not be
found, the programmer can look up the unfound words in the
ERROR.LOG file and repair the source code.


10.5 Interpreter words glossary

$COMPILE           "string-compile"                        EXTRA
    ( c-addr u -- )
    Try to find the name c-addr u in the search order and when
    found execute it or compile it according to the flag returned
    by FIND . Else try to convert the string to a number and
    compile it.  Else issue a warning that the word can not be
    found and compile a forward reference to it.

$INTERPRET         "string-interpret"                      EXTRA
    ( c-addr u -- )
    Try to find the name c-addr u in the search order and execute
    it when found else convert the string to a number and place it
    on the stack. Else abort with an exception message.

'COMPILE           "tick-compile"                          EXTRA
    ( c-addr u -- )
    A word that normally executes $COMPILE .

'INTERPRET         "tick-interpret"                        EXTRA
    ( c-addr u -- )
    A word that normally executes $INTERPRET .

2LITERAL           "two-literal"                           FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( x1 x2 -- )
    Append the run-time semantics defined below to the current
    definition.
    
    Run-time: ( -- x1 x2 )
    Place cell pair x1 x2 on the stack.

ANS                                                        EXTRA
    ( -- )
    Mark the most recently created definition as a standard word.
    When the variable ANSI does not contain zero, the default
    interpreter issues a warning if words that are not marked are
    interpreted or compiled.

ANSI                                                       EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing true when messages
    will be given if non-standard words are encountered and false
    otherwise.

COMPILE,           "compile-comma"                         FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Execution: ( xt -- )
    Append the execution semantics of the definition represented by
    xt to the execution semantics of the current word definition.

COMPILE-ONLY                                               EXTRA
    ( -- )
    Mark the most recently created definition as a compile-only word.
    The default interpreter issues exception -14 when an attempt is
    made to execute the definition in interpret state.

EVALUATE                                                   FORTH
    ( i*x c-addr u -- j*x )
    Save the current input source specification. Store minus one
    in SOURCE-ID . Make the string described by c-addr and u both
    the input source and input buffer, set >IN to zero, and
    interpret. When the parse area is empty, restore the prior
    input source specification. Other stack effects are due to the
    words EVALUATEd.

FORWARD                                                    ERRORLOG
    ( c-addr u -- )
    Compiled when during loading an undefined word is encountered
    in a colon definition. As an alias of EVALUATE , it will
    evaluate a string with the name of the unfound word. This can
    be used to create forward references.

IMMEDIATE                                                  FORTH
    ( -- )
    Mark the most recently created definition as an immediate word.

INTERPRET                                                  EXTRA
    ( -- )
    Interpret the current input stream.

LITERAL                                                    FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( x -- )
    Compile x as a literal. Append the run-time syntax given below
    to the current definition.
    
    Run-time: ( -- x )
    Place x on the stack.

LITERALS                                                   EXTRA
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( x1 .. xn n -- )
    Append the execution semantics defined below to the current
    definition.
    
    Executing:
    ( -- x1 .. xn )
    Place x1 to xn on the stack.

NOOP               "no-op"                                 EXTRA
    ( -- )
    Does nothing.

QUERY                                                      FORTH
    ( -- )
    Make the user input device the input source. Receive input into
    the terminal input buffer, replacing any previous contents. Make
    the result, whose address is returned by TIB , the input buffer.
    Set >IN to zero. 
    
    Note: this word is obsolescent and is included as a concession to
    existing implementations.

QUIT                                                       FORTH
    ( -- )
    Empty the return stack, store zero in SOURCE-ID , make the
    user input device the input source, and enter interpretation
    state. Do not display a message. Repeat the following:
     - Accept a line forth the input source into the input buffer,
       set >IN to zero and interpret.
     - Display the implementation defined input prompt if in
       interpretation state, all processing has been completed,
       and no ambiguous condition exists.

STATE               
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    ( -- a-addr )
    a-addr is the address of a cell containing the compilation state
    flag. STATE is true when in compilation state, false otherwise.
    The true value in STATE is non-zero, but is otherwise
    implementation-defined. Only the following standard words alter
    the value in STATE : : (colon), ; (semicolon), ABORT , QUIT ,
    :NONAME , [ (left-bracket), ] (right-bracket) and ;CODE .
    
    Note: A Standard Program may not directly alter the contents of
    STATE .
    See also: : :NONAME ; ABORT QUIT [ ]

TERMINAL                                                   EXTRA
    ( -- )
    Reset the input and output to the terminal.

========================================
11. Error recovery

The ANSI Standard offers a consistent way for error recovery.
This is done by a non-local return mechanism implemented by the
words CATCH and THROW just as in LISP and the words SETJMP en
LONGJMP in C.

CHForth offers also a way to define your own exception messages
and redefine existing messages.

Newer books will use the word exception instead of error because
it is more general and sometimes no error did occur at all.


11.1 CATCH and THROW

No word in CHForth handles its own exceptions, but the words in
which an exception may occur all return a value on the stack,
that differs from zero when an exception occured and is zero when
nothing went wrong. Then by placing the word THROW next to the
previous word, a zero on the stack will be dropped and the
program will continue, but a non-zero number will look for a
so-called exception frame on the return stack. This frame is
pushed there by the word CATCH . The depth of the data stack
before CATCH was called is restored as is the depth of the return
stack. The exception number will be on the stack and execution
will continue after CATCH instead after THROW . The user than can
take measures when a certain exception number will appear on the
stack. When no exception occured in a word that was executed by
CATCH, a zero will be left on top of the stack.

In QUIT is also a CATCH . This CATCH word catches all exceptions
it receives of INTERPRET , this word reads a line from the
terminal and tries to interpret this. Any errors are displayed on
the screen with the error number, the type (is this a standard
message, a message of DOS or a message of CHForth that is not
standard) and the message that is assigned to this number with
the word MESS" and then follows the line where the exception
occurred. When this exception occured during loading of a text
file or a blocks file, this information is also written to a text
file called error.log, so you can see where the errors occurred
at a more convenient time.


11.2 Examples

    : read-key
            KEY [CHAR] Q = THROW    \ Error when 'Q' pressed
            CR ." OK "              \ No error, CATCH leaves 0
        ;

    : main
            CR ." Press 'Q' to stop"
            BEGIN
            ['] read-key CATCH      \ Try to catch an error
            UNTIL                   \ 'Q' stops, others continue
        ;

    -13 MESS" unbekanntes Wort"     \ Redefine a message

    ' UNSINN                        \ May give the new message


11.3 Error messages

These messages are given when you type the number followed by
.MESS . The address of the counted string can now be found in
ERR$ and the number in ERR# . Beware that these become invalid
when another exception occurs. In QUIT these are the messages
that are given when any exception occurs. You can generate new
messages for these numbers with MESS" . In this way you could for
example make Dutch messages.

11.3.1 Standard ANS Forth messages

   -3 stack overflow
   -4 stack underflow
   -5 returnstack overflow
   -6 returnstack underflow
   -8 dictionary overflow
   -9 invalid memory address
  -10 division by zero
  -11 result out of range
  -13 undefined word
  -14 interpreting a compile-only word
  -15 invalid FORGET
  -16 attempt to use zero-length string as a name
  -22 control structure mismatch
  -25 returnstack imbalance
  -28 user interrupt
  -29 compiler nesting
  -32 invalid name argument
  -33 block read exception
  -34 block write exception
  -35 invalid block number
  -36 invalid file position
  -37 file I/O exception
  -38 non-existent file
  -49 search-order overflow
  -50 search-order underflow
  -57 exception in sending or receiving a character
  -58 missing terminating [ELSE] or [THEN]

11.3.2 DOS messages

First number is the exception number, second the standard DOS
error number.

 -511   1 function number invalid
 -510   2 file not found
 -509   3 path not found
 -508   4 too many open files (no handles available)
 -507   5 access denied
 -506   6 invalid handle
 -505   7 memory control blocks destroyed
 -504   8 insufficient memory
 -503   9 memory block address invalid
 -502  10 environment invalid
 -501  11 format invalid
 -500  12 access code invalid
 -499  13 data invalid
 -497  15 invalid drive
 -496  16 attempted to remove current directory
 -495  17 not same device
 -494  18 no more files
 -493  19 disk write-protected
 -492  20 unknown unit
 -491  21 drive not ready
 -490  22 unknown command
 -489  23 data error (CRC)
 -488  24 bad request structure length
 -487  25 seek error
 -486  26 unknown media type (non-DOS disk)
 -485  27 sector not found
 -484  28 printer out of paper
 -483  29 write fault
 -482  30 read fault
 -481  31 general failure
 -480  32 sharing violation
 -479  33 locking violation
 -478  34 disk change invalid
 -477  35 FCB unavailable
 -476  36 sharing buffer overflow
 -451  61 print queue full
 -450  62 queue not full
 -449  63 not enough space to print file
 -432  80 file exists
 -430  82 cannot make directory
 -429  83 fail on INT 24h
 -428  84 too many redirections
 -427  85 duplicate redirections
 -426  86 invalid password
 -425  87 invalid parameter

11.3.3 Messages of this Forth system

 -513 is not unique
 -514 execution halted
 -515 wrong use of DPSWAP
 -516 no defining word
 -517 not defining methods
 -518 is undefined, compiling forward reference
 -519 listsegment full
 -520 headersegment full
 -521 program contains errors
 -522 local stack overflow
 -523 local stack underflow
 -524 illegal opcode for this processor
 -525 unresolved forward definition
 -526 no special routine for this character
 -527 is not portable 
 -528 or part of it is not yet implemented
 -529 is in a non-portable number format 
 -530 already defining methods
 -531 character can not be converted
 -532 missing terminating ENDDOC
 -533 missing terminating *)

Message 0 will display the copyright message.


11.4 Error words glossary

!CSP               "store-c-s-p"                           EXTRA
    ( -- )
    Save the current depth of the stack for checking with ?CSP .

.MESS                                                      EXTRA
    ( n -- )
    Display the message that is assigned to exception number n as
    with MESS" . If the message is not found, display the exception
    number and the name of the word where the exception occured. If n
    is -1 or -2 nothing is displayed. Store the number in ERR# .

.WHERE                                                     EXTRA
    ( -- )
    If the last exception occurred during loading of a file, display
    the name of the file and the line number where the exception
    occurred.

?CSP               "question-c-s-p"                        EXTRA
    ( -- )
    Check the current depth of the stack with the one stored by !CSP
    Exception -29 will occur when they do not match.

?ERROR             "question-error"                        EXTRA
    ( x n -- )
    If x is not zero, exception n occurs. Else drop both numbers
    from the stack and continue.

?PAIRS             "question-pairs"                        EXTRA
    ( x1 x2 -- )
    Check x1 and x2. Exception -22 occurs when they are not equal.

?STACK             "question-stack"                        EXTRA
    ( -- )
    Check the three stack pointers and when they are too low or
    too high, exception -3, -4, -5, -6, -522 or -523 will occur.

ABORT                                                      FORTH
    ( i*x -- ) ( R: j*x -- )
    Perform the function of -1 THROW . When no other exception frame
    is present other than the one pushed by QUIT , empty the stacks
    and perform QUIT . When no file is currently open, display no
    message. Otherwise, contrary to the Standard, display some
    information about the file and the line where ABORT was called.
    Store a zero-length string in ERR$ .

ABORT"             "abort-quote"                           FORTH
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( "ccc<quote>" -- )
    Parse characters ccc delimited by " (double-quote). Append the
    run-time semantics specified below to the current definition.
    
    Run-time: ( i*x x1 -- | i*x ) ( R: j*x -- | j*x )
    Remove x1 from the stack. If any bit of x1 is not zero, perform
    the function of -2 THROW . The default interpreter will display
    ccc. The address of the counted string ccc can be found in ERR$ ,
    but is only valid for a limited time.

CATCH                                                      FORTH
    ( i*x xt -- j*x 0 | i*x n )
    Push an exception frame on the exception stack and then execute
    the execution token xt (as with EXECUTE ) in such a way that
    control can be transferred to a point just after CATCH if THROW
    is executed during the execution of xt.
    
    If the execution of xt completes normally (i.e. the exception
    frame pushed by this CATCH is not popped by an execution of THROW
    ) pop the execution frame and return zero on top of the data
    stack, above whatever stack items would have been returned by xt
    EXECUTE . Otherwise, the remainder of the execution semantics are
    given by THROW .

ERR#               "error-number"                          EXTRA
    ( -- x )
    Return the number of the last exception.

ERR$               "error-string"                          EXTRA
    ( -- c-addr )
    Return the address of the count of the last exception string.

ERRLINE            "error-line"                            EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing the line number of the
    file where an exception occurred.

ERRNAME            "error-name"                            EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing the address of the
    counted string representing the name of the file where an
    exception occurred.

ERROR-TYPE                                                 EXTRA
    ( -- )
    Show the type of the last exception number stored in ERR# by
    .MESS . Display nothing if ERR# equals -1 or -2.

MESS"              "mess-quote"                            EXTRA
    ( n "ccc<quote>" -- )
    Parse ccc delimited by a " (double-quote) and compile the string
    in the dictionary. The string is displayed when n is passed to
    .MESS or THROW .

NOT-IMPLEMENTED                                            EXTRA
    ( -- )
    Abort with exception message: not implemented, used in some
    definitions.

SHOW-ERROR                                                 EXTRA
    ( n -- )
    Display the exception message and information where the exception
    with number n occurred and the type of the exception and display
    the source line with the exception word marked out.

THROW                                                      FORTH
    ( k*x n -- k*x | i*x n )
    If any bits of n are non-zero, pop the topmost exception frame
    from the exception stack, along with everything on the return
    stack above that frame. Then restore the input source
    specification in use before the corresponding CATCH and adjust
    the depths of all three stacks so that they are the same as the
    depth saved in the exception frame (i is the same number as i in
    the input arguments to the corresponding CATCH ), put n on top of
    the data stack, and transfer control to a point just after the
    CATCH that pushed that exception frame.

WARNING                                                    EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing true when the program
    will warn the user when redefinitions are encountered and false
    otherwise.

========================================
12. The assembler

The assembler, if not already in memory, can be loaded by
    NEEDS -assembler

This is a full 8086 assembler that works in prefix mode about the
same as the one in F-PC, that is opcodes precede the destiny and
the source, different from traditional postfix Forth assembler
like the one in F83.

When using CHF386 the assembler is extended with some
instructions known only to 386 and 486 CPU's like 32 bit data
manipulation, although no 32 bit adressing, as CHForth runs in
real or virtual 8086 mode.


12.1 Register use

The BX register is always contains the top element of the stack,
the other elements are adressed via SP. The returnstack is
adressed via BP. Both stacks reside in the stacksegment, the
value of it is in the register SS. The local stack is only
accessible by system words.

When entering a code definition, the AX register contains its
starting address, that is useful if you make defining words with
;CODE. The code segment, CS is equal to DS.

The list segment with the colon definitions is kept in ES and the
offset of the Forth instruction pointer in SI.

The direction bit must be clear when returning to Forth, when you
use STD always do CLD at the end of your code.

The use of CX, DX and DI is not restricted.

When the destiny is a register or a register indirect mode,
always append a comma to it.


12.2 Examples

CODE D+         ( d1 d2 -- d3 )
                POP     CX              \ pop low word of d2
                POP     DX              \ pop high word of d1
                POP     AX              \ pop low word of d1
                ADD     AX, CX          \ add low part
                ADC     BX, DX          \ add high part
                PUSH    AX              \ push low part
                NEXT                    \ high part in BX
END-CODE                                \ check errors

Remember that the 80x86 series are low end machines and ANS Forth
is on word-level a high end machine: the word order is the other
way round. As it happens, 2@ of an Intel pointer places the
offset on top, as is necessary in -x words, so many problems do
not arise in high level words. When you push or pop 32 bit data,
remember to swap both halves.

The assembler for the 386 version can generate code for 32 bit
data, but not for 32 bit addresses as it runs in real or virtual
86 mode. So the previous example can be rewritten as:

CODE D+         ( d1 d2 -- d3 )
                ROL     EBX, # #16      \ shift high word left
                POP     BX              \ pop low word
                POP     EAX             \ pop 32 bit operand
                ROL     EAX, # #16      \ swap high and low words
                ADD     EBX, EAX        \ do the operation
                PUSH    BX              \ push low word
                ROL     EBX, # #16      \ high word to bx
                NEXT                    \ return to Forth
END-CODE                                \ check errors

Some adressing modes:

Intel:                  CHForth:

pop     ax              pop     ax
pop     [bx]            pop     0 [bx]      \ always an offset
pop     [bx+23]         pop     23 [bx]
pop     es:[bp+si-32]   pop     es: -32 [bp+si]
push    [1234]          push    1234        \ direct address
mov     ax,cs:[bx]      mov     ax, cs: 0 [bx]
mov     cs:[bx],ax      mov     cs: 0 [bx], ax
mov     ax,[1234]       mov     ax, 1234    \ direct address
mov     ax,1234         mov     ax, # 1234  \ immmediate
mov     [1234],ax       mov     1234 ax     \ direct address
mov     al,12           mov     al, # 12
mov     al,[1234]       mov     al, 1234 [] \ direct address
mov     [1234],al       mov     1234 [], al \ byte adressing
mov     byte ptr 12,'A' mov     12 [], # 'A' byte
                                    \ [], # and byte all requred
mov     word ptr 12,21  mov     12 # 21
add     bx,[bx]         add     bx, 0 [bx]
mov     al,12           mov     al, # 12    \ immediate mode
sar     bx              sar     bx, # 1     \ # 1 is necessary
out     dx,al           out     dx, al
out     12,ax           out     12 #, ax    \ only use for #,
in      ax,dx           in      ax, dx
in      al,12           in      al, # 12

Only when #CPU contains #386 :

Intel:                  CHForth:

push    1234            push    # 1234      \ immediate
push    ebx             push    ebx         \ 32 bit data
pop     dword [ebx]     pop     sz: 0 [bx]  \ 16b adr, 32b data
pop     [ebx]           not implemented     \ 32b address
rcl     ebx,14          rcl     ebx, # 14   \ only 386


12.3 Structures

Like the compiler structures in high level Forth, the assembler
also knows control flow structures. For example:

CODE ?DUP               ( x -- x x | x )
                TEST    BX, BX  \ When top of stack is not zero
        0<> IF
                PUSH    BX      \ Push it on the stack
        THEN
                NEXT            \ Top of stack still in BX
END-CODE

As you see, the jump words like IF, WHILE, UNTIL are postfix, the
condition like 0= 0<> U< come before them. Without IF and THEN
the example can be rewritten using labels:

CODE ?DUP               ( x -- x x | x )
                TEST    BX, BX  \ When top of stack is zero
                JZ      0 $     \ jump to label
                PUSH    BX      \ Push it on the stack
        0 $:    NEXT            \ Top of stack still in BX
END-CODE

The labels consist of $: preceded with a number in the range
0..31 and the jumps have the corresponding number followed by $.

When using the 386 version, the conditional jumps like JZ will
compile a 16 bit LJZ when the offset is too large for a signed
byte. You can not use the labels with 'n $' for this, use real
addresses for example:
                JAE     $1223
                JL      $4504
In the 86 version you have be more inventive, like this:
        U>= IF
                JMP     $1223
        THEN
                JGE     4 $
                JMP     $4504
        4 $:

When you need to use words like , in a code definition you have
to put a A; before using it because the assembler will execute
opcodes after all of its parameters are defined and so the , will
interfere. A better method to compile data is using words DW and
DB that handle this problem.

CODE SWAP
            DB  $58             \ POP AX
            DB  'S'             \ PUSH BX
            DW  $D88B           \ XCHG BX, AX
            NEXT
            A; ", finished!"    \ compile an inline counted string
END-CODE

Use JB for JNAE (or JC) and JGE for JL etcetera, as I have deleted
the JNx words.


12.4 Assembler words glossary

#                                                          ASSEMBLER
    ( x -- x )
    Immediate mode for source.

#,                                                         ASSEMBLER
    ( x -- x )
    Immediate mode for destiny.

$                                                          ASSEMBLER
    ( x -- )
    Jump to an assembler label.

$:                                                         ASSEMBLER
    ( x -- )
    Define an assembler label.

$ELSE                                                      ASSEMBLER
    ( -- )
    Jump to after $THEN .

$IF386                                                     ASSEMBLER
    ( -- )
    If #CPU does not contain 386 jump to after $ELSE or $THEN .
    Else continue.

$THEN                                                      ASSEMBLER
    ( -- )
    Terminate a $IF386 directive.

;CODE                                                      ASSEMBLER
    Interpretation: ( i*x -- )
    This word is marked compile only. The default interpreter issues
    exception -14 when an attempt is made to execute this word.
    
    Compilation: ( C: colon-sys -- )
    Append the execution semantics defined below to the current
    definition. End the current definition, consuming colon-sys,
    enter interpret state, add the ASSEMBLER word list to the search
    order and start interpreting the rest of the parse area and
    assemble machine code. If needed, refill the input buffer until
    END-CODE is processed.
    
    Execution: ( -- ) ( R: nest-sys -- )
    Replace the execution semantics of the most recently defined word
    with the name execution semantics given below. Return control to
    the calling definition specified by nest-sys. An ambiguous
    condition exists if the most recently defined word was not
    defined with CREATE or a user-defined word that calls CREATE .
    
    name Execution: ( i*x -- j*x )
    Perform the machine code sequence that was generated following
    ;CODE .
    See also: DOERCODE DOES> END-CODE

A;                                                         ASSEMBLER
    ( -- )
    Terminate a line of assembly code.

ASSEMBLER                                                  ASSEMBLER
    ( -- )
    Replace the first word list in the search order with the
    ASSEMBLER word list.

CODE                                                       ASSEMBLER
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a definition for name, called a "code definition", with
    the execution semantics defined below. Add the ASSEMBLER word
    list to the search order and start interpreting the rest of the
    parse area and assemble machine code. If needed, refill the input
    buffer until END-CODE is processed.
    
    name Execution: ( i*x -- j*x )
    Execute the machine code sequence that was generated following
    CODE .
    See also: END-CODE

DB                                                         ASSEMBLER
    ( "ccc" -- )
    Assemble "ccc" as an 8 bit value.

DOERCODE                                                   ASSEMBLER
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a definition for name with the execution semantics defined
    below. Enter interpret state, add the ASSEMBLER word list to the
    search order and start interpreting the rest of the parse area
    and assemble machine code. If needed, refill the input buffer
    until END-CODE is processed.
    
    Execution: ( -- ) ( R: nest-sys -- )
    Replace the execution semantics of the most recently defined word
    with the name execution semantics given below. Return control to
    the calling definition specified by nest-sys. An ambiguous
    condition exists if the most recently defined word was not
    defined with CREATE or a user-defined word that calls CREATE .
    
    name Execution: ( i*x -- j*x )
    Perform the machine code sequence that was generated following
    DOERCODE .
    See also: DOES> END-CODE

DW                                                         ASSEMBLER
    ( "ccc" -- )
    Assemble "ccc" as a 16 bit value.

END-CODE                                                   ASSEMBLER
    ( -- )
    Resolve all assembler labels, terminate the current code
    definition and allow its name to be found in the dictionary.
    Remove the ASSEMBLER word list from the search order.

L$                                                         ASSEMBLER
    ( -- addr )
    Define a forward near label in assembler, one per definition.

L$:                                                        ASSEMBLER
    ( addr -- )
    Resolve a forward near label.

[]                                                         ASSEMBLER
    ( -- )
    Direct mode for source.

[],                                                        ASSEMBLER
    ( -- )
    Direct mode for destiny.

========================================
13. How about flyer
========================================
14. Using doer:
========================================
15. Defining methods
========================================
16. The TO-concept
========================================
17. Interrupt handling

The hardware and software of the personal computer is largely
controlled through the use of interrupts. Of course Forth is
provided with tools to use them. Also some interrupts are used by
the CHForth itself.


17.1 Used interrupts

Interrupt 0 is called when a division overflow or a division by
zero occurs. CHForth redirects the vector to a routine that
issues ANS Forth exception -10. This interrupt is reset to its
previous value when leaving CHForth with BYE or HALT.

Interrupt 6 is called when a non-existing opcode is encountered.
CHForth redirects the vector to a routine that issues CHForth
exception -524. This hardware feature is implemented on the 80286
processors and newer but is harmless on a 8086. This interrupt is
reset to its previous value when leaving CHForth with BYE or
HALT.

Interrupt 1B is called when BIOS receives a Ctrl-Break action.
CHForth redirects the vector to a routine that issues ANS Forth
exception -28. This interrupt is reset to its previous value when
leaving CHForth with BYE or HALT.

Interrupt 1C is called 18.2 times a second by the clock. It is
currently not used in CHForth, but can be changed. This interrupt
is reset to its previous value when leaving CHForth with BYE or
HALT.

Interrupt 23 is called when DOS receives a Ctrl-Break or Ctrl-C
action. CHForth redirects the vector to a routine that discards
the key. Directly after this BIOS takes over and issues interrupt
1B, described above. The value of this interrupt is not saved in
Forth because when the program terminates, DOS itself will
restore it.


17.2 Examples

To get the value of an interupt is by GET-INTERRUPT:
    $13 GET-INTERRUPT
will leave the segment and offset of the BIOS disk routines on
the stack.
    $FF00 $0FF0 $13 SET-INTERRUPT
will set the address, in this case the system restart address.
Whenever a disk access is needed, in a Disk Operating System very
often, the computer will restart in this example without saving
your code. So here you have very dangerous toys in your hands!.

The word INTVEC is also provided to use the interrupts as if it
were objects like VALUEs. The last word is used in the library
file CLOCK where interrupt 1C is changed. You may load it by
saying  NEEDS clock  and after  CLOCKON  you will see a digital
clock in the upper-right corner of the screen and with  CLOCKOFF
it is hidden.


17.3 Interrupt words glossary

GET-INTERRUPT                                              EXTRA
    ( n -- x-addr )
    Return the extended address x-addr of the interrupt vector n.

INTVEC             "interrupt-vector"                      INTVEC
    ( x "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a definition for name with the execution semantics defined
    below. Name is referred to as an "interrupt vector".
    
    name Executing: ( -- x-addr )
    Place x-addr, the extended address of the current vector assigned
    to interrupt number x. The value of this vector can be changed by
    executing 'addr TO name', can be reset to its initial value by
    'CLEAR name' and the number x can be obtained by executing 'FROM
    name'. To get the address where the default value is stored, use
    'ADR name'.

SET-INTERRUPT                                              EXTRA
    ( x-addr n -- )
    Set interrupt vector n to extended address x-addr.

========================================
18. The decompiler

The decompiler, if not already in memory, can be loaded by
    NEEDS -decompiler

As a result of the threaded code mechanism there is a nearly
one-to-one relationship between source and object code. The
decompiler is a program that helps the programmer to view
compiled code in a form that resembles the source for that code.


18.1 What can be decompiled

- Colon definitions with inline literals, locals and compiler
  structures.
- Constants
- Variables
- Definitions made with Create
- Vocabularies


18.2 What can not be decompiled

Code definitions like DROP, 2@, EXIT can not be decompiled with
the standard decompiler, see chapter 19, the disassembler.


18.3 Examples

see space
: SPACE
        BL EMIT
        ;   ans  ok

As you see most words are written in capital letters, and some
indentation is helpful to view the structure of the words. The
decompiled text could even be placed in a logfile and after some
editing made ready for reloading. The last word 'ans' signifies
compliance to the standard.

see spaces
: SPACES
        0 MAX 0
        ?do     SPACE
        Loop
        ;   ans  ok

Literals between -9 and 9 are printed as decimal digits. Other
numbers as four digit hexadecimal numbers with a leading dollar
sign. Compiler directives as ?DO and LOOP are printed with one
capital followed by lower case letters.

' bl (see)
CONSTANT BL             $0018     32 ok

The word (SEE) expects an execution token on the stack and
decompiles the word associated with it. The value of the constant
is printed as well in hexadecimal as in decimal.


18.4 Decompiler words glossary

(SEE)                                                      DECOMPILER
    ( xt -- )
    Decompile the definition that has xt as its execution token.

ALL                                                        DECOMPILER
    ( -- )
    Decompile all words in the context word list.

BTW                                                        DECOMPILER
    ( "name1" "name2" -- )
    Decompile all words in the context word list between "name1"
    and "name2" inclusive, the order does not matter.

DECOMPILER                                                 DECOMPILER
    ( -- )
    Set the context to the DECOMPILER word list.

NO.                                                        DECOMPILER
    ( -- )
    The decompiler shows only the names of the definitions.

SEE                                                        DECOMPILER
    ( "name" -- )
    Parse "name" delimited by spaces and decompile or disassemble
    it.

TILL                                                       DECOMPILER
    ( "name" -- )
    Decompile all words in the context word list newer than "name"
    and itself.

YES.                                                       DECOMPILER
    ( -- )
    Set decompiler to normal.

========================================
19. The disassembler

This disassembler can display the assembler code from code
definitions in Forth and any code in the 1 Mb of the PC and the
first 64 Kb of the HMA on AT and higher machines.

The disassembler, if not already in memory, can be loaded by
    NEEDS -disassembler


19.1 What can be disassembled

Code in Forth can be disassemble by using the word DIS or, when
the decompiler is loaded before the dissassembler, also by SEE.
Code in other segments can be decompiled by DISX.


19.2 What can not be disassembled

When you use CHForth-86 it is not possible to decompile specific
386 code. CHForth-386 can decompile some enhanced instructions,
but I did not find it necessary to provide a solution for all
opcodes.

Only data that belong to a known Forth word, such as a variable
or a constant is displayed as data. But, although this is a
symbolic disassembler, most data in Forth does not have labels,
so it is shown as if it was code. so care is to be taken when
interpreting what you see.


19.3 Examples

FORTH> see +
\   +  ans
cseg:0828  pop     ax                        58                     X
cseg:0829  add     bx,ax                     03D8                   ..
cseg:082B  next                              26ADFFE0               &...

When an address can be associated with a header, the name is
printed along with flags as ANS, IMMEDIATE, COMPILE-ONLY and
HIDDEN. The other lines start with the segment, when in Forth one
of the five symbols: cseg, lseg, hseg, eseg or stac is used,
otherwise the hexadecimal value. Then the offset followed with
the code on that address. After the middle follows the display
of bytes, first in hex, at the end with SEMIT.

The sequence
            LODSW   ES:
            JMP     AX
is displayed with the name of the macro.

FORTH> ' if dis
\   IF  immediate compile-only ans
cseg:11D8  jmp     docolon $031E             E9DBEFFC1E03           ......
\   ELSE  immediate compile-only ans
cseg:11DE  jmp     docolon $032A             E9D5EFFC2A03           ....*. ok

As CHForth generates data on aligned adresses, jumps and calls at
the start of definitions are followed by a byte $FC(that is the
instruction CLD that here never is executed). The address after
docolon is the start of the colon definition in LSTSEG.

FORTH> ' bl dis
\   BL  ans
cseg:01DE  jmp     doconstant $0020          E99FFFFC2000           .... .
\   FALSE  ans
cseg:01E4  jmp     doconstant $0000          E999FFFC0000           ...... ok

Interrupt vectors can be dissassembler by this method:
        $21 GET-INTERRUPT DISX


19.4 Disassembler words glossary

DIS                "disassemble"                           DISASSEMBLER
    ( addr -- )
    Disassemble from address addr.

DISASSEMBLER                                               DISASSEMBLER
    ( -- )
    Replace the first wordlist in the search order with the
    DISASSEMBLER word list.

DISX               "dis-extended"                          DISASSEMBLER
    ( x-addr -- )
    Disassemble from extended address x-addr.

SEE                                                        DECOMPILER
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Find name. If name can not be found exception -13 occurs.
    If name is high level, decompile it. Otherwise if the
    disassembler is loaded, disassemble it.

========================================
20. The viewer

The viewer, if not already in memory, can be loaded by
    NEEDS -view

As a result of the threaded code mechanism there is a nearly
one-to-one relationship between source and object code. The
viewer is a program that helps the programmer to view compiled
code in a form that resembles the source for that code albeit in
less explicit form than with the decompiler. The viewer is a
simple type of decompiler and takes much less room than the
decompiler or disassembler.


20.1 What can be viewed

- Colon definitions with inline literals, locals and compiler
  structures.
- Constants
- Variables
- Definitions made with Create
- Vocabularies


20.2 What can not be viewed

Code definitions like DROP, 2@, EXIT will be shown as if they
were data, see chapter 19, the disassembler.


20.3 Examples

FORTH> view space
cseg:23E2 : SPACE
            lseg:1ADA  01E8  BL
            lseg:1ADC  0374  EMIT
            lseg:1ADE  06A2  ;

The number on the far left is the address in the code segment.
The colon is the type of the definition and SPACE is its name. As
this is a colon definition, the next lines are indented and the
address in the list segment is showed first, with the contents
following it. On the right is the name of each compiled word.

FORTH> view spaces
cseg:23E8 : SPACES
            lseg:1AE0  06AD   $0000  False
            lseg:1AE4  0CCB  MAX
            lseg:1AE6  06AD   $0000  False
            lseg:1AEA  06FE  ?DO    lseg:1AF2
            lseg:1AEE  23E2  SPACE
            lseg:1AF0  0725  LOOP
            lseg:1AF2  06A2  ;

Literals printed as four digit hexadecimal numbers with a leading
dollar sign. Some numbers like -1 and 0 are printed further as
TRUE or FALSE. Values between 1 and 31 are printed as control
characters and values between 32 and 127 as characters. Compiler
directives as ?DO and ELSE are printed with a jump address after
it.

FORTH> ' bl (view)
cseg:01E8 CONSTANT BL
cseg:01EC   0020    ' '      ' .'

The word (VIEW) expects an address on the stack and views the
code that is there in the codesegment. The hexadecimal value of
the constant is printed. The value is followed by a ascii value
when it is displayable or a decimal value if not. At the and
ASCII dump of the two bytes is given in single quotes.


20.4 Viewer words glossary

(VIEW)                                                     VIEW
    ( addr -- )
    Display data in the code segment from addr.

VIEW                                                       VIEW
    ( "name" -- )
    Find "name" in the search-order or convert it to an address.
    Display one line at the time of data with, space continues,
    other keys terminate.

========================================
21. The interface with DOS

As Forth gives access to nearly every part of the computer
system, words to access the internal memory and external ports is
available.


21.1 The DOS environment

DOS reserves a segment to store the environment strings when a
program is loaded. Its segment number in CHForth is returned by
ESEG and its size in paragraphs by ELEN.
For example, if you want to know the value of the DOS PATH
variable, simply use
    S" PATH=" SEARCH-ENVIRONMENT
to return the string. Remember that the string given by S" has to
be in uppercase. This is just the way the CHForth string variable
COMSPEC is initialized to get the name and path of the operating
system command interpreter.


21.2 External ports

The eight and sixteen bit ports of the PC can be accessed by the
words PC@ and PC! or P@ and P! respectively. For example,
    $61 PC@ 3 OR $61 PC!
puts the speaker on.


21.3 The screen

The text screen segment is in the constant SBASE that is
initialized when the program is started and contains $B800 on
color and $B000 on monochrome systems. For example
    $0720 SBASE 0 !X
puts a space (20) with black background and white foreground (07)
in the leftmost position on the first line of the screen.

The textmode is set with TEXT or TEXT0 that restores the textmode
to that when CHForth was started. When you have a Speedstar Pro
videoboard TEXT1 gives 132x25 text screen and TEXT2 a 132x43
textscreen. The size of the screen, inclusive the attribute bytes
is returned by SCREENSIZE, so you could save the screen in memory
or on disk. Other modes can be set by SETMODE and asked by
GETMODE. To use this consult the manual of your video adapter.

You can get the with of the screen from C/L and the height with
L/SCR . On some systems the latter is always set to 25 as the
byte at 40:84 is not defined for the PC/XT. The current character
attribute is in the variable ATTR and the the default in the
variable ATT0 . Inverse characters are emitted after INVERS ,
blinking occurs after BLINK , highlight after BRIGHT and the
opposite is done with -INVERS -BLINK and -BRIGHT . The default
value is reset by NORMAL .

The screen is addressable with HOME and AT-XY and the cursor
position is returned by ?AT . You can position the cursor on the
current line with HTAB .


21.4 The DOS interface glossary

?AT                "question-at"                           EXTRA
    ( -- u1 u2 )
    Return the column x1 and row x2 of the cursor on the screen.

AT-XY              "at-x-y"                                FORTH
    ( u1 u2 -- )
    Perform steps so that the next character displayed will appear in
    column u1, row u2 of the current output device, the upper left
    corner of which is row zero, column zero. It is a no-op when the
    operation cannot be performed on the current output device with
    the specified parameters. Note that for other implementations the
    result in that case is an ambiguous condition.

ATT0               "attribute-zero"                        EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing the default attribute
    of the characters on the screen.

ATTR               "attribute"                             EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing the current attribute
    of the characters on the screen.

BEEP                                                       EXTRA
    ( -- )
    Make an alarm sound on the speaker. As this is sometimes
    irritating, try CLICK .

BEEPH                                                      EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing the frequency in Hertz
    of BEEP.

BEEPL                                                      EXTRA
    ( -- a-addr )
    a-addr is the address of a cell containing the duration in
    milliseconds of BEEP.

BIOS-IO                                                    EXTRA
    ( -- )
    Set input and output to fast BIOS routines, redirection is not
    supported.
    See also: MS-DOS-IO

BIOS?              "bios-query"                            EXTRA
    ( -- x )
    A value that is true when output goes via fast BIOS and not
    via slow DOS.

BLINK                                                      EXTRA
    ( -- )
    Invert the blink character attribute.

BLOCK-CURSOR                                               EXTRA
    ( -- )
    Set the cursor form to a block.

BRIGHT                                                     EXTRA
    ( -- )
    Invert the bright character attribute.

C/L                "c-per-l"                               EXTRA
    ( -- n )
    Return the number of characters on a screen line.

CLICK                                                      EXTRA
    ( -- )
    Make a more pleasant sort of BEEP.

CONSOLE!           "console-store"                         EXTRA
    ( char -- )
    Write char to the standard output file.

CONSOLE?           "console-query"                         EXTRA
    ( -- x )
    A value that is true when screen output is enabled.

CONSOLE@           "console-fetch"                         EXTRA
    ( -- char | -1 )
    Read character char from the standard input file. If the end of
    the file is reached, return -1.

DEALLOC                                                    EXTRA
    ( u -- ior )
    Return the contiguous region of memory outside the data space
    indicated by the segment address u to the system for later
    allocation. u shall indicate a region of memory outside the data
    space that was previously obtained by ALLOC or REALLOC . If no
    exception occurs ior is zero. Othewise ior is the I/O result
    code.

DFTMODE            "default-mode"                          EXTRA
    ( -- )
    Set the screen to the textmode that was current at program start.

ECHO                                                       EXTRA
    ( -- )
    When loading echo the lines read to the screen.

ECHO?              "echo-query"                            EXTRA
    ( -- x )
    A value that is true when characters are echoed during loading a
    textfile.

ELEN                                                       EXTRA
    ( -- n )
    n is the number of paragraphs in the environment segment.

EOL                "e-o-l"                                 EXTRA
    ( -- )
    Emit spaces to clear the line on the screen beyond the cursor.

ESEG                                                       EXTRA
    ( -- x )
    x is the value of the DOS environment segment.

GET-DIRECTORY                                              EXTRA
    ( -- c-addr u ior )
    Get the current directory as a character string specified by
    c-addr u. The path is preceded by the drive letter and a colon.
    If no exception occurs, ior is zero. Otherwise c-addr and u are
    unspecified and ior is the I/O result code.

GET-INTERRUPT                                              EXTRA
    ( n -- x-addr )
    Return the extended address x-addr of the interrupt vector n.

GETDISK                                                    EXTRA
    ( -- n )
    n is the current drive number.

GETMODE                                                    EXTRA
    ( -- n )
    n is the number of the current screen mode.

HIDE-CURSOR                                                EXTRA
    ( -- )
    Hide the cursor.

HOME                                                       EXTRA
    ( -- )
    Set the cursor on the top left of the screen.

HTAB               "h-tab"                                 EXTRA
    ( u -- )
    If n is greater than zero, emit spaces until the cursor is at
    column u of the current user output device.

INVERS                                                     EXTRA
    ( -- )
    Exchange the character foreground and background colors.

L/SCR              "l-per-s-c-r"                           EXTRA
    ( -- n )
    Return the number of lines on the screen.

LINE-CURSOR                                                EXTRA
    ( -- )
    Set the cursor form to a line.

MS-DOS-IO                                                  EXTRA
    ( -- )
    Set input and output to slow DOS routines, redirection is
    supported.
    See also: BIOS-IO CONSOLE! CONSOLE@

NOECHO                                                     EXTRA
    ( -- )
    When loading do not echo lines read to the screen.

NORMAL                                                     EXTRA
    ( -- )
    Reset to character attribute on the screen to the default
    value.

NOSOUND                                                    EXTRA
    ( -- )
    Turn the speaker off.

OUT                                                        EXTRA
    ( -- x )
    A value that contains the number of characters printed on the
    current screen line.

P!                 "p-store"                               EXTRA
    ( x1 x2 -- )
    Write x1 to 16 bit port x2.

P@                 "p-fetch"                               EXTRA
    ( x1 -- x2 )
    Read the 16 bit port x1.

PAGE                                                       FORTH
    ( -- )
    Move to another page for output. Actual function depends on the
    output device. On a terminal, PAGE clears the screen and resets
    the cursor position to the upper left corner. On a printer, PAGE
    performs a form feed.

PC!                "p-c-store"                             EXTRA
    ( char x -- )
    Write char to 8 bit port x.

PC@                "p-c-fetch"                             EXTRA
    ( x -- char )
    Read the 8 bit port x.

PITCH                                                      EXTRA
    ( n -- )
    Set the frequency of the speaker to n.

RESTORE-METRICS                                            EXTRA
    ( -- )
    When returning from a system call, reset some screen parameters.

SBASE              "s-base"                                EXTRA
    ( -- x )
    x is the segment number of the text screen.

SCREENSIZE                                                 EXTRA
    ( -- n )
    n is the total count of characters plus attributes on the screen.

SEARCH-ENVIRONMENT                                         EXTRA
    ( c-addr1 u1 -- c-addr2 u2 )
    Search the DOS environment strings for the string specified by
    c-addr1 u1. Return the character string after the first string as
    a character string specified by c-addr2 u2. If the string is not
    found, u2 is zero and c-addr2 is unspecified.

SEGMENT                                                    EXTRA
    ( x "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a definition for name with the execution semantics defined
    below. Leave the dictionary pointer at an aligned address.
    Allocate space for 3 cells. Ask DOS for an allocation of x
    paragraphs and store the segment number of that allocation in the
    first cell. Store x in the second cell and zero in the third. The
    user may change the value of the third cell to a value less than
    or equal to x in order to save the allocated area with the
    program.
    
    name Execution: ( -- a-addr )
    a-addr is the address of the first reserved cell of name.

SET-DIRECTORY                                              EXTRA
    ( c-addr u -- ior )
    Set the current directory to the string specified by c-addr u. As
    an extension to DOS, the default drive can also be changed if a
    drive letter and a colon are present at the beginning of the
    string. If no exception occurs, ior is zero. Otherwise ior is the
    I/O result code.

SET-INTERRUPT                                              EXTRA
    ( x-addr n -- )
    Set interrupt number n to extended address x-addr.

SETDISK                                                    EXTRA
    ( n1 -- n2 )
    Set the current drive to n1. n2 is the the total number of
    available drives.

SETMODE                                                    EXTRA
    ( n -- )
    Set the screen to mode n.

SHOW-CURSOR                                                EXTRA
    ( -- )
    Display the cursor.

SOUND                                                      EXTRA
    ( -- )
    Turn the speaker on.

TRAP                                                       EXTRA
    ( -- )
    Jump back the debugger program, use it when you want to step
    through Forth.

========================================
22. Maintenance of program files

This chapter assumes that you have an editor, preferably SZ.COM
or NE.COM at your disposal.


22.1 Generating new source files

One way to create program files is to type EDIT optionally
followed with a filename. No extension is needed, as the default
is .FRT set in the counted string FEXT$ . The format of the files
is plain ASCII and can include tabs but because in DOS this is
always fixed to eight positions, this is too rigid to be useful.

A more uniform file format with headers and footers is obtained
by typing PROJECT followed by the filename. The editor is entered
at a place where you can start typing. The strings that can be
customized are PROJ$ CAT$ and CREAT$ that are in the file
CHFORTH.CFG.


22.2 Library files

Some program parts are used in other programs so it might be
convenient to put them in a separate file. Words that are
included in the Standard are already in CHFORTH.EXE but some
words that are typed "obsolescent" in the Standard are found in
the file LIB\OBSOLETE.FRT and can be loaded in with
    NEEDS -obsolete
if you need them. A decompiler, disassembler and logger are not
always needed, so you can put a \ (backslash) in front of the
line in CHFORTH.CFG where they are loaded with NEEDS .

There is realy no difference in the files in the current
directory from the files in the LIB directory, both can be loaded
with IN followed by their path and name, but NEEDS does the same
without a path for the files in LIB so you can place these files
anywhere provided you change the line with LIBPATH in CHFORTH.CFG
accordingly.

Most library files have a MARKER word in front of them, as the
system of libraries is modulary, the list of loaded files can be
displayed by .MODULES .


22.3 Logging

All the user or the program displays on the screen can be logged
to a file. Pressing F2 (when ACCEPT.FRT is loaded) or typing
OPEN-LOG will create a file called FORTH.LOG or append to an
existing file with that name. The statusline is disabled. The
logging is ended by pressing F2 again, typing CLOSE-LOG or
automatically by typing BYE . The file name can be changed, it is
in the counted string at LOGFILE .

Needed file: LIB\LOG.FRT


22.4 Glossary generation

Automatic glossary generation (making of help files) is possible.
The word \G is an alias for \ so interpreting will skip the lines
that have it in front of it. The glossary generator however,
parses the following string and will put them along with the
following defined word in a glossary file. With NEW-GLOSS you
reset the generator. MAKE-GLOSS followed by the full filename
will load and parse the file and this may be repeated until all
the files are processed or the memory is full. WRITE-GLOSS will
write the data to a file, extension preferably .HLP and directory
DOC so the word HELP can immediately be used.

Needed file: MAKEHELP.FRT


22.5 Maintenance words glossary

,EDIT                                                      EDITOR
    ( u "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Open file name with the editor program and place the cursor at
    line u. When name is omitted, the last opened file by this
    command or EDIT LIST or WHAT is opened and name is displayed on
    the right of the status line. The default extension is taken from
    FEXT$ .

.MODULES                                                   EXTRA
    ( -- )
    Display the list of words that are created by MARKER .

?DEF               "query-defined"                         EXTRA
    ( "name" -- flag )
    Skip leading space delimiters. Parse name delimited by a space.
    Find name. If name is found, flag is true, false otherwise.
    See also: ?UNDEF

?UNDEF             "query-undefined"                       EXTRA
    ( "name" -- flag )
    Skip leading space delimiters. Parse name delimited by a space.
    Find name. If name is found, flag is false, true otherwise.
    See also: ?DEF

CAT$                                                       EXTRA
    ( -- c-addr )
    c-addr is the address of a counted string containing a
    description of the category to which this file belongs.

CLOSE-LOG                                                  LOG
    ( -- )
    Close the logfile.

CREAT$                                                     EXTRA
    ( -- c-addr )
    c-addr is the address of a counted string containing the name of
    the creator of this file.

EDIT                                                       EDITOR
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Open file name with the editor program and place the cursor at
    the first line. When name is omitted, the last opened file by
    this command or ,EDIT LIST or WHAT is opened and name is
    displayed on the right of the status line. The default extension
    is taken from FEXT$ .

EDLIB                                                      EDITOR
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Open file name in the directory given in LIBPATH with the editor
    program and place the cursor at the first line. The default
    extension is taken from FEXT$ .

LIBPATH                                                    EXTRA
    ( -- c-addr )
    c-addr is the address of a counted string containing the path to
    the library files.
    See also: HELPPATH NEEDS

LOGFILE                                                    LOG
    ( -- c-addr )
    Contains the name of the logfile.

GLOSS              "glossary"                              FORTH
    ( "fname1" "fname2" -- )
    Make a glossary with name2 out of the origin file name1 .

MAKE-GLOSS         "make-glossary"                         FORTH
    ( "name" -- )
    This word reads a source file and builds the glossary information
    for it in memory.

NEEDS                                                      EXTRA
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Find name. If found continue. Otherwise, load the file with the
    same name (excluding an optional trailing minus sign) from the
    directory specified in LIBPATH .

NEW-GLOSS          "new-gloss"                             FORTH
    ( -- )
    This command starts a fresh glossary.

OPEN-LOG                                                   LOG
    ( -- )
    Open the logfile.

PROJ$                                                      EXTRA
    ( -- c-addr )
    c-addr is the address of a counted string containing a
    description of the project for which the file is created.

PROJECT                                                    PROJECT
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Create a text file for name with the default extension in FEXT$ .
    Write a header as defined in the strings PROJ$ CAT$ and CREAT$
    and start the editor with the cursor at a place where the
    programmer can start typing. This file can be loaded directly
    after editing by typing IN . After the header is a MARKER for
    an automatic FORGET when reloading the file.

WHAT                                                       EDITOR
    ( -- )
    Open file name with the editor program and place the cursor at
    the line number stored in ERRLINE . name is stored at the address
    stored in ERRNAME . ERRNAME and ERRLINE are valid after an
    exception that occured during loading of file name. name is
    displayed on the right of the status line.

WRITE-GLOSS        "write-glossary"                        FORTH
    ( "name" -- )
    This word writes the glossary info from memory into a file.
    The information may be collected from several source files.

\G                                                         EXTRA
    ( "ccc<eol>" -- )
    If BLK contains zero, parse and discard the remainder of the
    parse area; otherwise parse and discard the portion of the parse
    area corresponding to the remainder of the current line. \G is an
    immediate word. Used in generating glossaries.

========================================
23. Turnkey programs

With CHForth it is possible to write programs that run
independent like a filter utility or a game. In such programs an
interpreter or compiler is not necessary. As yet it is not
possible to delete the compiler and interpreter, but it is easy
to ignore them.


23.1 Trimming the system

There are three words, RESERVE LRESERVE and HRESERVE that make it
possible to trim the three main segments of CHForth. If for
example you need a Forth program with interpreter and compiler
that needs only 4 Kb space in each segment to compile a few words
after it is loaded and nothing more, you could use the following:
    4096 RESERVE    \ Reserve no more than 4 Kb for data
    4096 LRESERVE   \ Reserve only 4 Kb for colon definitions
    4096 HRESERVE   \ Reserve no more than 4 Kb for headers
    SAVE SMALLF     \ Make a program SMALLF.EXE
This is nice to be used as a normal CHForth program on systems
that do not have 640 Kb conventional memory, the three segments
are now each less than 64 Kb in the memory of the computer.
Remember to never put data above LIMIT LLIMIT or HLIMIT as they
are just beyond the last usable address in their segments. If you
need an interpreter but no compiler, you could use 0 for all
three RESERVE words, as there will always be some space above
HERE for interpreting input.


23.2 Self running programs

A second method is the use of the word TURNKEY . First write a
word that does the job that you want to do and then save the
program:
    EMPTY                       \ Discard any unnecessary code
    : GO            ( -- )      \ Program can not use parameters
        'Z' 1+ 'A'
        DO      I EMIT
        LOOP                    \ No BYE necessary
    ;
    TURNKEY GO ALPHABET         \ Make program ALPHABET.EXE
After this you are in DOS, type the name of the program after the
prompt and now you see the alphabet and then the DOS prompt.

This technique uses 0 RESERVE 0 LRESERVE to trim the code and
list segment and wholly discard the head segment, so interpreting
is not possible as headers are not present.


23.3 Examples

Some examples are to be found in \TURNKEY . All can be compiled
at the DOS prompt by:
    CHFORTH IN filename
Or by executing:
    MAKE -ffilename
If you have the MAKE utility.

Most programs give some information about their workings when you
type the name followed by a space and /? or -?


23.4 Turnkey glossary.

.FREE              "dot-free"                              EXTRA
    ( -- )
    Display the value of the three dictionary pointers and the free
    space in their respective segments.

HLIMIT                                                     EXTRA
    ( -- x )
    Return the address after the last usable in the head segment.

HMEMTOP                                                    EXTRA
    ( -- addr )
    Return the address after the last physical address in the header
    segment.

HRESERVE                                                   EXTRA
    ( x -- )
    Reserve x address units above HHERE in the head segment to be
    used by the compiler in a saved program. When x is zero, all
    headers of the definitions are discarded in the saved program.

LIMIT                                                      EXTRA
    ( -- x )
    Return the address after the last usable in the dictionary.

LLIMIT                                                     EXTRA
    ( -- x )
    Return the address after the last usable in the list segment.

LMEMTOP                                                    EXTRA
    ( -- addr )
    Return the address after the last physical address in the list
    segment.

LRESERVE                                                   EXTRA
    ( x -- )
    Reserve x address units above LHERE in the list segment to be
    used by the compiler in a saved program. When x is zero, no
    compiling is possible in the new program.

MEMTOP                                                     EXTRA
    ( -- addr )
    Return the address after the last physical address in memory.

RESERVE                                                    EXTRA
    ( x -- )
    Reserve x address units above HERE to be used by ALLOT in a
    saved program. Some space is always available in PAD and
    TEMPORARY so interpreting remains possible if x is zero.

RESTART?                                                   EXTRA
    ( -- x )
    A value that prohibits restarting of the initialisation of a
    program. When the program is started its value is false. When
    Ctrl-Break is pressed, it is set to true.

SAVE                                                       EXTRA
    ( "name" -- )
    Skip leading space delimiters. Parse name delimited by a space.
    Protect the dictionary as with EXTEND . Write the CHForth program
    as an executable file with this name. name may have a preceding
    path but no extension. The current settings of LIMIT and MEMTOP
    are preserved as are their equivalents in other segments.

TURNKEY                                                    EXTRA
    ( "name1" "name2" -- )
    Skip leading space delimiters. Parse name1 delimited by a space.
    Skip leading space delimiters. Parse name2 delimited by a space.
    Protect the dictionary as with EXTEND . Write the CHForth program
    as an executable file with this name2. name2 may have a preceding
    path but no extension.
    
    The saved file does not contain any headers, so interpreting in
    the executible file is not possible. The data space and list
    space will also be reduced to the minimum value that is needed to
    containt the current data in the data and list space. Both spaces
    can be enlarged before executing this word.
    
    When this program is executed from the DOS prompt, name1 will be
    executed by CATCH and at the end the control will be returned to
    DOS. The program saved has no capability to compile and has no
    headers.

UNUSED                                                     FORTH
    ( -- u )
    u is the amount of space remaining in the region addressed by
    HERE , in address units.

========================================
24. CHForth internals

Traditionally Forth has been implemented as a small model, where
code, data, colon definitions, stacks and headers were in one
memory space, the dictionary. In CHForth some differentiation has
been made.


24.1 Code space

In the codesegement are placed all data outside colon definitions
and low level code routines.

Code definitions start without special entering code, as CHForth
is direct threaded code, contrary to indirect threaded code, the
way FIGFORTH and F83 were implemented, where a pointer preceded
every definition. Returning to the next routine is done via the
macro NEXT in assembler, that loads the word pointed to by ES:SI
into the AX register, increments SI by two to point the next time
to the next word (postincrement) and jumps to the address in AX.

Variables and words that are built with CREATE without DOES> have
a jump instruction to special code that pushes the inline address
on the stack. This could have been a call instruction, but as the
top of the stack in CHForth is in a register and for speed a jump
seemed faster. Just after the jump is a byte with value $FC,
which is the code for the instruction CLD, faster than NOP, but
that is of no importance, as it is never executed and only serves
to keep HERE aligned. The word >BODY is simply '2 CELLS +' or '4
+' as a cell is 2 characters or bytes. The address after the CLD
instruction is called the data field.

Constants and values are made in the same way, a jump to a
special routine which pushes the value in the data field on the
the stack and then the data itself.

Colon definitions have a jump to a special routine that pushes
the current Forth instruction pointer SI on the returnstack and
makes the contents of the datafield the next value of the Forth
instruction pointer. This now points to a list of compiled
execution tokens and is discussed in paragraph 24.3

The value of the code space is in the CS and DS register and its
value is returned by the word CSEG. Access of this memory area is
with the traditional @ ! and , etc.


24.2 Header space

To reserve more space in the code segment, a header segment is
present, which has all the headers of the definitions.

A header is identified by its dictionary entry address, this is
returned by the word >HEAD.

- It starts with link field, that points to the previous word in
  the current word list.

- Then follows a cell with flags, of which the immediate bit is
  the most important.

- This is followed by a cell containing a pointer to the forget
  code associated with this type of word, when there does not
  exist such a routine, it is zero.

- Next is the pointer to the execution token in the code space.

- At the end is a byte with the count of characters in the name
  followed with the name itself and padded with a null byte when
  necessary to make the dictionary entry address even.

Creating a header does not allocate space in the code segment, so
making an ALIAS is very simple.

Never use knowledge about the current order of the header fields,
this may change in the future, for example, I may add a hashing
mechanism to speed up compilation.

The value of the header space is returned by the word HSEG.
Access of its data is with H@ H! and H, etc.


24.3 List space

The value in the datafield of colon definitions is a pointer to a
list of compiled execution tokens (the essence of Forth) that are
interpreted one by one by the NEXT macro (in native code Forths
this list can be a series of machine code calls and other machine
code). This list is placed in another memory space, the
listsegment.

In the list space are also placed literal numbers and inline
strings compiled by ." .

Literal numbers have a preceding execution token that will push
the inline value on the stack.

The value of the list space is in the ES register and is returned
by the word LSEG. Access is with L@ L! and L, etc.


24.4 String space

Strings compiled by ABORT" S" and C" have a pointer in the list
segment that points to the address of the string in the code
segment, where the strings themselves are compiled, so on
execution the strings can be TYPEd CMOVEd and COUNTed. Direct
execution of S" will still compile the string in the a special
area in the code space due to the word FLYER and execute them
immediately afterwards to place the address and length on the
stack. This area is 1024 bytes large and will accept up to four
256 byte long strings and more if they are shorter, there is an
overflow area of 256 bytes at the end.


24.5 Stack space

CHForth has three stacks.

- The first is the data stack, normally called simply the stack
  where numbers, execution tokens and flags are stored. Access is
  with DUP SWAP DROP PICK ROLL and so forth. The number of
  elements on the stack is given by DEPTH .

- The second is the return stack, called so because its function
  is mainly to keep return addresses when nesting occurs by
  entering colon definitions. It also contains information for
  do-loops, for-next loops and can temporary be used by words as
  >R and R> to transfer values from the datastack to the return
  stack and vice versa.

- The third stack is only used to store local variables. No
  operators to access this stack apart from the local variables
  themselves are available.

The value of the stack space is in the SS register and is
contained in the variable STKSEG in the INTERNAL word list. As it
is not necessary to access the stacks directly, no special
accessing words are given. For this the words PICK and ROLL are
provided. Never use constructs from other Forths as: : EMIT  SP@
1 TYPE DROP ; This will definitely not work!


24.6 DOS space

DOS reserves a segment to store the environment strings when a
program is loaded. See chapter 21.

Access of the memory outside of CHForth is provided by the word
SEGMENT . It needs a number of paragraphs (16 byte chunks) on the
stack and a name. Using the name gives access to an array of 3
cells of which the first gives the value of the segment in the
640 Kb that is available for DOS. In the second cell is the
number of paragraphs. The area is automatically returned to DOS
when you forget this word. When have filled the area with data
you can place a value giving the size of the area in paragraphs
and put it in the third cell. When you save the program, the data
will also be saved and will later be available if you execute the
program. Of course the value of the segment can then be
different, but that is because DOS assigns segments to its memory
allocation. Data is accessed by @X !X COUNTX etc. where the
appendix -X is short for extended address. The extended address
is always in the form segment-offset, where the low word is the
segment and the high word is the offset.

Example:

    $100 SEGMENT MYDATA     \ Allocate $100*$10 (4096) bytes.
    MYDATA @                \ Get the segment
    0                       \ An offset
    MYDATA CELL+ @          \ the size
    PARAGRAPHS              \ convert it to byte count
    DUMPX                   \ dump it
    1234 MYDATA @ 20 !X     \ store some data in it
    ( FORGET MYDATA )       \ Return the area to DOS
    700 #PARAGRAPHS         \ Convert to paragraphs
    MYDATA 2 CELLS + !      \ Keep 700 bytes when you save this
    SAVE MYPROG             \ Save CHForth along with MYDATA

========================================
24. Examples
========================================
25. Main glossary
========================================
26. Alphabetical index of words
========================================
