The following option equates are set if not already before *\i{kernel62.fth) is compiled.
0 equ DeferPrompt? \ --
Set this true (non-zero) to defer the interactive prompt.
1 equ BigKernel? \ --
Set this false to reduce the kernel size and lose some
words.
variable next-user \ -- addr
Next valid offset for a USER
variable created by +USER
.
: +user \ size --
Creates a USER
variable size bytes long at the offset given
by NEXT-USER
and updates it.
tcb-size +user SELF \ task identifier and TCB
When multitasking is enabled by setting the equate TASKING?
the task control block for a task occupies TCB-SIZE
bytes at
the start of the user area. Thus the user area pointer
also acts as a pointer to the task control block.
cell +user S0 \ base of data stack
Holds the initial setting of the data stack pointer.
N.B. S0
, R0
, #TIB
and 'TIB
must be
defined in that order.
cell +user R0 \ base of return stack
Holds the initial setting of the return stack pointer.
cell +user #TIB \ number of chars currently in TIB
Holds the number of characters currently in TIB
.
cell +user 'TIB \ address of TIB
Holds the address of TIB
, the terminal input buffer.
cell +user >IN \ offset into TIB
Holds the current character position being processed in the
input stream.
cell +user XON/XOFF \ true if XON/XOFF protocol in use
True when console is using XON/XOFF protocol.
cell +user ECHOING \ true if echoing
True when console is echoing input characters.
cell +user OUT \ number of chars displayed on current line
Holds the number of chars displayed on current output line.
Reset by CR.
cell +user BASE \ current numeric conversion base
Holds the current numeric conversion base
cell +user HLD \ used during number formatting
Holds data used during number formatting
cell +user #L \ number of cells converted by NUMBER?
Holds the number of cells converted by NUMBER?
cell +user #D \ number of digits converted by NUMBER?
Holds the number of digits converted by NUMBER?
cell +user DPL \ position of double number character id
Holds the number of characters after the double number indicator
character. DPL
is initialised to -1, which indicates a
single number, and is incremented for each character after
the separator.
cell +user HANDLER \ used in catch and throw
Holds the address of the previous exception frame.
cell +user OPVEC \ output vector
Holds the address of the I/O vector for the current output device.
cell +user IPVEC \ input vector
Holds the address of the I/O vector for the current input device.
cell +user 'AbortText \ Address of text from ABORT"
Set by the run-time action of ABORT"
to hold the address
of the counted string used by ABORT" <text>"
.
cell +user FSP \ -- addr
Floating point stack pointer. Created if FP-SIZE
is
non-zero.
cell +user FS0 \ -- addr
Top of floating point stack. Created if FP-SIZE
is
non-zero.
#64 chars dup +user PAD
A temporary string scratch buffer.
Various constants for the internal system.
FALSE |
The well formed flag version for a logical negative |
TRUE |
The well formed flag version for a logical positive |
BL |
An internal constant for blank space |
C/L |
Max chars/line for internal displays under C/LINE |
#VOCS |
Maximum number of Vocabularies in search order |
VSIZE |
Size of |
XON |
XON character for serial line flow control |
XOFF |
XOFF character for serial line flow control |
Note that FENCE
, DP
and VOC-LINK
must be
declared in that order.
WIDTH |
maximum target name size |
FENCE |
protected dictionary |
DP |
dictionary pointer |
VOC-LINK |
links vocabularies |
RP |
Harvard targets only. The equivalent of DP for DATA space. |
SCR |
If |
BLK |
If |
CURRENT |
Vocabulary/wordlist in which to put new definitions |
STATE |
Interpreting=0 or compiling=-1 |
CSP |
Preserved stack pointer for compile time error checking |
CONTEXT |
Search order array |
LAST |
Points to name field of last definition |
#THREADS |
Default number of threads in new wordlists |
defer NUMBER? \ addr -- d/n/- 2/1/0
Attempt to convert the counted string at 'addr' to an integer.
The return result is either 0 for failed, 1 for a single-cell
return result (followed by that cell) or 2 for a double-cell return.
The ASCII number string supplied can also contain implicit radix
over-rides. A leading $ enforces hexadecimal, a leading # enforces
decimal and a leading % enforces binary. Hexadecimal numbers can
can also be specified by a leading '0x' or trailing 'h'.
When one of the floating point packs is compiled,
the action of NUMBER?
may be changed.
defer ERROR \ n -- ; error handler
The standard error handler reports error n. If the system is
loading, the offending line will be displayed. Now implemented
by default as a synonym for THROW
.
Removed from v6.2 onwards. Use THROW
instead.
FORTH |
Is the standard general purpose vocabulary |
ROOT |
This vocabulary holds the bare minimum functions |
The standard console Forth I/O words (KEY?
, KEY
,
EMIT
, TYPE
and CR
) can be used with any I/O
device by placing the address of a table of xts in the
USER
variables IPVEC
and OPVEC
. IPVEC
(input vector) controls the actions of KEY?
and KEY
,
and OPVEC
(output vector) controls the actions of EMIT
,
TYPE
and CR
.
Adding a new device is matter of writing the five primitives,
building the table, and storing the address of the table in
the pointers IPVEC
and OPVEC
to make the new
device active. Any initialisation must be performed before
the device is made active.
Note that for the output words (EMIT
, TYPE
and
CR
) the USER
variable OUT
is handled in the
kernel before the funtion in the table is called.
The example below is taken from an ARM implementation.
create Console1 \ -- addr
' serkey1i , \ -- char
' serkey?1i , \ -- flag
' seremit1 , \ char --
' sertype1 , \ c-addr len --
' serCR1 , \ --
Console1 opvec ! Console1 ipvec !
: KEY? \ -- flag ; check receive char
Return true if a character is available at the current input
device.
: KEY \ -- char ; receive char
Wait until the current input device receives a character and
return it.
: EMIT \ -- char ; display char
Display char on the current I/O device. OUT
is incremented
before executing the vector function.
: TYPE \ caddr len -- ; display string
Display/write the string on the current output device.
Len is added to OUT
before executing the vector function.
: CR \ -- ; display new line
Perform the equivalent of a CR/LF pair on the current output
device. OUT
is zeroed. before executing the vector
function.
: TYPEC \ caddr len -- ; display string
Display/write the string from CODE space on the current
output device.
Len is added to OUT
before executing the vector function.
N.B. Harvard targets only. In non-Harvard targets, this is a
synonym for TYPE
.
: SPACE \ --
Output a blank space (ASCII 32) character.
: SPACES \ n --
Output 'n' spaces, where 'n' > 0.
If 'n' < 0, no action is taken.
: FlushKeys \ --
Compiled for 32 bit systems to flush any pending input that
might be returned by KEY
.
: SetConsole \ device --
Sets KEY
and EMIT
and friends to use the given
device for terminal I/O. Compiled for 32 bit systems, but is
also part of LIBRARY.FTH.
: [io \ -- ; R: -- ipvec opvec
Save the current I/O devices on the return stack.
: io] \ -- ; R: ipvec opvec --
Restore the I/O devices from the return stack.
Some of these words may be coded for performance. If they are predefined, the high level versions will not be compiled.
For byte-addressed CPUs (nearly all except DSPs) this kernel assumes that a character is an 8 bit byte, i.e. that:
char = byte = address-unit
: PLACE \ c-addr1 u c-addr2 -- ; copies uncounted string to counted
Place the string c-addr1/u as a counted string at c-addr2.
: BOUNDS \ addr len -- addr+len addr
Modify the address and length parameters to provide an end-address
and start-address pair suitable for a DO ... LOOP
construct.
: UPC \ char -- char'
If char is in the range 'a' to 'z' convert it to upper case.
UPC
is English language specific.
: UPPER \ c-addr u --
Convert the ASCII string described to upper-case. This operation
happens in place.
Note that this word is language specific and is written to
handle English only.
: ERASE \ a-addr u --
Erase U bytes of memory from A-ADDR with 0.
: BLANK \ a-addr u --
Blank U bytes of memory from A-ADDR using ASCII 32 (space).
: HERE \ -- addr
Return the current dictionary pointer which is the first
address-unit of free space within the system.
: ALLOT \ n --
Allocate N address-units of data space from the current value of
HERE
and move the pointer.
: aligned \ addr -- addr'
Given an address pointer this word will return the next
ALIGNED
address subject to system wide alignment
restrictions.
: ALIGN \ --
ALIGN
dictionary pointer using the same rules as
ALIGNED
.
: LATEST \ -- c-addr
Return the address of the name field of the last definition.
: SMUDGE \ --
Toggle the SMUDGE
bit of the latest definition.
: , \ x --
Place the CELL value X into the dictionary at HERE
and
increment the pointer.
: W, \ w --
Place the WORD value X into the dictionary at HERE
and
increment the pointer. This word is not present on 16 bit
implementations.
: C, \ char --
Place the CHAR value into the dictionary at HERE
and
increment the pointer.
: there \ -- addr
Harvard targets only: Return the DATA space pointer.
: allot-ram \ n --
Harvard targets only: ALLOT
DATA space.
: c,(r) \ b --
Harvard targets only: The equivalent of C,
for DATA space.
: ,(r) \ n --
Harvard targets only: The equivalent of ,
for DATA space.
: N>LINK \ a-addr -- a-addr'
Move a pointer from a NFA field to the Link Field.
: LINK>N \ a-addr -- a-addr'
The inverse of N>LINK
.
: >LINK \ a-addr -- a-addr'
Move a pointer from an XT to the link field address.
: LINK> \ a-addr -- a-addr'
The inverse of >LINK
.
: >VOC-LINK \ wid -- a-addr
Step from a wordlist identifier, wid, to the address of the
field containg the address of the previously defined wordlist.
: >#THREADS \ wid -- a-addr ; for XC5 compatibility
Step from a wordlist identifier, wid, to the address of the
field containg the number of threads in the wordlist.
: >THREADS \ wid -- a-addr
Step from a wordlist identifier, wid, to the address of the
array containing the top NFA for each thread in the wordlist.
: >VOCNAME \ wid -- a-addr
Step from a wordlist identifier, wid, to the address of the
field pointing to the vocabulary name field.
: FIND \ c-addr -- c-addr 0|xt 1|xt -1
Perform the SEARCH-WORDLIST
operation on all wordlists
within the current search order. This definition takes a
counted string rather than a c-addr/u pair. The counted
string is returned as well as the 0 on failure.
: .NAME \ nfa --
The correct way to display a definition's name given an NFA.
string for a word name, return the address of the dictionary
name thread that will contain the name.
: makeheader \ c-addr len --
Given a word name as a string in addr/len form, build a
dictionary header for the word.
: $CREATE \ c-addr --
Perform the action of CREATE
(below) but take the name from
a counted string. OBSOLETE: replace by:
count makeheader docreate,
: CREATE \ --
Create a new definition in the dictionary. When the new definition
is executed it will return the address of the definition BODY.
: (C") \ -- c-addr
The run-time action for C"
which returns the address of and
steps over a counted string.
: (S") \ -- c-addr u
The run-time action for S"
which returns the address and
length of and steps over a string.
: (ABORT") \ i*x x1 -- | i*x
The run time action of ABORT"
.
: (.") \ --
The run-time action of ."
.
Before the ANS Forth standard, these words were the primary
error handlers. They are provided for compatibility, but
wherever possible, the use of CATCH
and THROW
will
be found to be more flexible.
: ABORT \ i*x -- ; R: j*x --
Performs -1 THROW
. This is a compatibility word for earlier
versions of the kernel. Unfortunately, the earlier versions
gave problems when ABORT
was used in interrupt service
routines or tasks. The new definition is brutal but consistent.
: ABORT" \ Comp: "ccc<quote>" -- ; Run: i*x x1 -- | i*x ; R: j*x -- | j*x
If x1 is non-zero at run-time, store the address of the
following counted string in USER
variable 'ABORTTEXT
,
and perform -2 THROW
. The text interpreter in QUIT
will (if reached) display the text.
: (Error) \ n --
The default action of ERROR
.
This definition has been removed from v6.2 onwards.
See the section about the changes from v6.1 to v6.2.
: ?ERROR \ flag n --
If flag is true, perform "n ERROR", otherwise do nothing.
This definition has been removed from v6.2 onwards.
See the section about the changes from v6.1 to v6.2.
CATCH
and THROW
form the basis of all Forth error
handling. The following description of CATCH
and
THROW
originates with Mitch Bradley and is taken from
an ANS Forth standard draft.
CATCH
and THROW
provide a reliable mechanism for
handling exceptions, without having to propagate exception
flags through multiple levels of word nesting. It is similar
in spirit to the "non-local return" mechanisms of many other
languages, such as C's setjmp() and longjmp(),
and LISP's CATCH and THROW. In the Forth context,
THROW
may be described as a "multi-level EXIT", with
CATCH
marking a location to which a THROW
may return.
Several similar Forth "multi-level EXIT" exception-handling
schemes have been described and used in past years. It is not
possible to implement such a scheme using only standard words
(other than CATCH
and THROW
), because there is no
portable way to "unwind" the return stack to a predetermined
place.
THROW
also provides a convenient implementation technique
for the standard words ABORT
and ABORT"
, allowing
an application to define, through the use of CATCH
, the
behavior in the event of a system ABORT
.
This sample implementation of CATCH
and THROW
uses the non-standard words described below. They or their
equivalents are available in many systems. Other
implementation strategies, including directly saving the
value of DEPTH
, are possible if such words are not
available.
SP@ |
( -- addr ) returns the address corresponding to the top of data stack. |
SP! |
( addr -- ) sets the stack pointer to addr, thus restoring the stackdepth to the same depth that existed just before addr was acquired by executing SP@. |
RP@ |
( -- addr ) returns the address corresponding to the top of return stack. |
RP! |
( addr -- ) sets the return stack pointer to addr, thus restoring thereturn stack depth to the same depth that existed just before addr wasacquired by executing RP@. |
nnn USER HANDLER 0 HANDLER ! \ last exception handler
: CATCH ( xt -- exception# | 0 ) \ return addr on stack
SP@ >R ( xt ) \ save data stack pointer
HANDLER @ >R ( xt ) \ and previous handler
RP@ HANDLER ! ( xt ) \ set current handler
EXECUTE ( ) \ execute returns if no THROW
R> HANDLER ! ( ) \ restore previous handler
R> DROP ( ) \ discard saved stack ptr
0 ( 0 ) \ normal completion
;
: THROW ( ??? exception# -- ??? exception# )
?DUP IF ( exc# ) \ 0 THROW is no-op
HANDLER @ RP! ( exc# ) \ restore prev return stack
R> HANDLER ! ( exc# ) \ restore prev handler
R> SWAP >R ( saved-sp ) \ exc# on return stack
SP! DROP R> ( exc# ) \ restore stack
\ Return to the caller of CATCH because return
\ stack is restored to the state that existed
\ when CATCH began execution
THEN
;
The ROM PowerForth implementation is similar to the one described above, but not identical.
If THROW
is executed with a non zero argument, the
effect is as if the corresponding CATCH
had returned it.
In that case, the stack depth is the same as it was just
before CATCH
began execution.
The values of the i*x stack arguments could have been modified
arbitrarily during the execution of xt. In general, nothing useful
may be done with those stack items, but since their number is known
(because the stack depth is deterministic), the application may
DROP
them to return to a predictable stack state.
Typical use:
: could-fail \ -- char
KEY DUP [CHAR] Q =
IF 1 THROW THEN
;
: do-it \ a b -- c
2DROP could-fail
;
: try-it \ --
1 2 ['] do-it CATCH IF
( -- x1 x2 ) 2DROP ." There was an exception" CR
ELSE
." The character was " EMIT CR
THEN
;
: retry-it \ --
BEGIN
1 2 ['] do-it CATCH
WHILE
( -- x1 x2 ) 2DROP ." Exception, keep trying" CR
REPEAT ( char )
." The character was " EMIT CR
;
If a THROW
is performed without a CATCH
in place,
the system will/may crash. As the current exception frame
is pointed to by the USER
variable HANDLER
,
each task and interrupt handler will need a CATCH
if
THROW
is used inside it.
You can no longer use ABORT
as a way of resetting the
data stack and calling QUIT
. ABORT
is now defined
as -1 THROW
.
: CATCH \ i*x xt -- j*x 0|i*x n
Execute the code at XT with an exception frame protecting it.
CATCH
returns a 0 if no error has occurred, otherwise it
returns the throw-code passed to the last THROW
.
: THROW \ k*x n -- k*x|i*x n
Throw a non-zero exception code n back to the last CATCH
call. If n is 0, no action is taken except to DROP
n.
: ?throw \ flag throw-code -- ; SFP017
Perform a THROW
of value throw-code if flag is non-zero,
otherwise do nothing except discard flag and throw-code.
: HEX \ --
Change current radix to base 16.
: DECIMAL \ --
Change current radix to base 10.
: OCTAL \ --
Change current radix to base 8. 32 bit targets only.
: BINARY \ --
Change current radix to base 2.
: HOLD \ char --
Insert the ascii 'char' value into the pictured numeric output
string currently being assembled.
: SIGN \ n --
Insert the ascii 'minus' symbol into the numeric output string if
'n' is negative.
: # \ ud1 -- ud2
Given a double number on the stack this will add the next digit to
the pictured numeric output buffer and return the next double
number to work with. PLEASE NOTE THAT THE NUMERIC OP STRING IS
BUILT FROM RIGHT (l.s. ddigit) to LEFT (m.s. digit).
: #S \ ud1 -- ud2
Keep performing #
until all digits are generated.
: <# \ --
Begin definition of a new numeric output string buffer.
: #> \ xd -- c-addr u
Terminate defnition of a numeric output string. Return the
address and length of the ASCII string.
: -TRAILING \ c-addr u1 -- c-addr u2
Modify a string address/length pair to ignore any trailing spaces.
: D.R \ d n --
Output the double number 'd' using current radix, right justified
to 'n' characters. Padding is inserted using spaces on the left
side.
: D. \ d --
Output the double number 'd' without padding.
: . \ n --
Output the cell signed value 'n' without justification.
: U. \ u --
As with . but treat as unsigned.
: U.R \ u n --
As with D.R but uses a single-unsigned cell value.
: .R \ n1 n2 --
As with D.R but uses a single-signed cell value.
: SKIP-SIGN \ addr1 len1 -- addr2 len2 t/f ; true if sign=negative
Inspect the first character of the string, if it is a '+'
or '-' character, step over the string. Returning true if the
character was a '-', otherwise return false.
: +DIGIT \ d1 n -- d2 ; accumulates digit into double accumulator
Multiply d1 by the current radix and add n to it.
: +CHAR \ char -- flag ; true if ok
This routine handles non-numeric characters, returning
true for valid characters. The only acceptable non-numeric
character are the double-number separator ',' and the
ignore separator ':', which is there to make 32 bit hex
numbers more readable.
: +ASCII-DIGIT \ d1 char -- d2 flag ; true=ok
Accumulate the double number d1 with the conversion of char,
returning true if the character is a valid digit or part of an
integer.
: (INTEGER?) \ c-addr u -- d/n/- 2/1/0
The guts of INTEGER?
but without the base override handling.
See INTEGER?
: Check-Prefix \ addr len -- addr' len'
If any BASE
override prefices or suffices are used
in the input string, set BASE
accordingly and return
the string without the override characters.
: Integer? \ $addr -- n 1 | d 2 | 0
Attempt to convert the counted string at 'addr' to an integer.
The return result is either 0 for failed, 1 for a single-cell
return result followed by that cell)or 2 for a double return.
The ASCII number string supplied can also contain implicit radix
over-rides. A leading $ enforces hexadecimal, a leading # enforces
decimal and a leading % enforces binary.
The prefix '@' is supported for octal numbers in 32 bit systems,
for which hexadecimal numbers can also be specified by a
leading '0x' or a trailing 'h'.
: >NUMBER \ ud1 c-addr1 u1 -- ud2 c-addr2 u2 ; convert all until non-digits
Accumulate digits from string c-addr1/u2 into double number ud1
to produce ud2 until the first non-convertible character is found.
c-addr2/u2 represents the remaining string with c-addr2 pointing
the non-convertible character. The number base for conversion is
defined by the contents of USER
variable BASE
.
>NUMBER
is now case insensitive.
: BS \ -- ; destructive backspace
Perform a destructive backspace by issuing ASCII characters
8, 20h, 8. If OUT
is non-zero at the start, it is decremented
by one regardless of the actions of the device driver.
: ?BS \ pos -- pos' step ; perform BS if pos non-zero
If pos is non-zero and ECHOING
is set, perform BS
and return the size of the step, 0 or -1.
: SAVE-CH \ char addr -- ; save as required
Save char at addr, and output the character if
ECHOING
is set.
: ." \ "ccc<quote>" --
Output the text upto the closing double-quotes character.
Use .( <text>)
when interpreting.
: $. \ c-addr -- ; display counted string
Output a counted-string to the output device.
Note that on Harvard targets (e.g. 8051) c-addr is in
DATA space.
: ACCEPT \ c-addr +n1 -- +n2 ; read up to LEN chars into ADDR
Read a string of maximum size n1 characters to the buffer at
c-addr, returning n2 the number of characters actually read. Input
may be terminated by CR. The action may be input device specific.
If ECHOING
is non-zero, characters are echoed.
If XON/XOFF
is non-zero, an XON character is sent at the
start and an XOFF character is sent at the the end.
0 value SOURCE-ID \ -- n ; indicates input source
Returns an indicator of which device is generating
source input. See the ANS specification for more details.
: TIB \ -- c-addr ; return address of terminal i/p buffer
Returns the address of the terminal input buffer. Note that
tasks requiring user input must initialise the USER
variable 'TIB
. New code should use SOURCE
and
TO-SOURCE
instead for ANS Forth compatibility.
: TO-SOURCE \ c-addr u --
Set the address and length of the system terminal input buffer.
These are held in the user variables 'TIB
and #TIB
.
: SOURCE \ -- c-addr u
Returns the address and length of the current terminal input
buffer.
: SAVE-INPUT \ -- xn..x1 n
Save all the details of the input source onto the data stack.
will do the job. If you want to move the data to the return
stack, N>R
and NR>
are available in some 32 bit
implementations.
: RESTORE-INPUT \ xn..x1 n -- flag
Attempt to restore input specification from the data stack. If
the stack picture between SAVE-INPUT
and
RESTORE-INPUT
is not balanced, a non-zero is returned
in place of N. On success a 0 is returned.
: QUERY \ -- ; fetch line into TIB
Reset the input source specification to the console and accept a
line of text into the input buffer.
: REFILL \ -- flag ; refill input source
Attempt to refill the terminal input buffer from the current
source. This may be a file or the console. An attempt to refill
when the input source is a string will fail. The return result
is a flag indicating success with TRUE and failure with FALSE.
A failure to refill when the input source is a text file indicates
the end of file condition.
: PARSE \ char "ccc<char>" -- c-addr u
Parse the next token from the terminal input buffer using
<char> as the delimiter. The next token is returned as a
c-addr/u
string description. Note that PARSE
does
not skip leading delimiters. If you need to skip leading
delimiters, use PARSE-WORD
instead.
: PARSE-WORD \ char -- c-addr u ; find token, skip leading chars
An alternative to WORD
below. The return is a
c-addr/u pair rather than a counted string and no copy
has occured, i.e. the contents of HERE
are unaffected.
Because no intermediate global buffers are used PARSE-WORD
is more reliable than WORD
for text scanning in multi-threaded
applications.
: WORD \ char "<chars>ccc<char>" -- c-addr
Similar behaviour to the ANS word PARSE
but the returned
string is described as a counted string.
: HALT? \ -- flag
Used in listed displays. This word will check the keyboard for a
'pause' key <space>, if the key is pressed it will then wait for
a continue key or an abort key. The return flag is TRUE if abort
is requested. Line Feed (LF, ASCII 10) characters are ignored.
: origin- \ addr -- addr'
If addr is non-zero, subtract the start address of the first
defined CDATA section.
This word is only compiled if the start address of the first
defined CDATA section is non-zero.
: origin+ \ addr -- addr' ; denormalise NFA again
If addr is non-zero, add the start address of the first
defined CDATA section.
This word is only compiled if the start address of the first
defined CDATA section is non-zero.
: nfa-buff \ -- addr+len addr ; make a buffer for holding NFAs
Form a temporary buffer for holding NFAs. A factor for
WORDS
.
: MAX-NFA \ -- addr c-addr ; returns addr and top nfa
Return the thread address and NFA of the highest word
in the NFA buffer. A factor for WORDS
.
: COPY-THREADS \ addr --
Copy the threads of the CONTEXT
wordlist to a
temporary NFA buffer for manipulation. A factor for
WORDS
.
: WORDS \ --
Display the names of all definitions in the wordlist at the
top of the search-order. For 32 bit targets, you can use
WORDS text
to display only those words containing text.
: MOVE \ src dest len -- ; intelligent move
An intelligent memory move, chooses between CMOVE
and
CMOVE>
at runtime to avoid memory overlap problems.
Note that as ROM PowerForth characters are 8 bit, there is
an implicit connection between a byte and a character.
: DEPTH \ -- +n
Return the number of items on the data stack, excluding the count.
: UNUSED \ -- u ; free dictionary space
Return the number of bytes free in the dictionary.
: .FREE \ --
Return the free dictionary space.
: WORDLIST \ -- wid
Create a new wordlist and return a unique identifier for it.
: VOCABULARY \ -- ; VOCABULARY <name>
Create a VOCABULARY
which is implemented as a named wordlist.
: FORTH \ --
Install FORTH
wordlist into search-order.
: FORTH-WORDLIST \ -- wid
Return the unique WID for the main FORTH wordlist.
: GET-CURRENT \ -- wid
Return the WID for the Wordlist which holds any definitions made
at this point.
: SET-CURRENT \ wid --
Change the wordlist which will hold future definitions.
: GET-ORDER \ -- widn...wid1 n
Return the list of WIDs which make up the current search-order.
The last value returned on top-of-stack is the number of WIDs
returned.
: SET-ORDER \ widn...wid1 n -- ; unless n = -1
Set the new search-order. N is the number of WIDs
to place in the search-order. If N is -1 then the minimum search
order is inserted.
: ONLY \ --
Set the minimum search order as the current search-order.
: ALSO \ --
Duplicate the first WID in the search order.
: PREVIOUS \ --
Drop the current top of search-order.
: DEFINITIONS \ --
Set the current top WID of search-order as the current definitions
wordlist.
: ?PAIRS \ x1 x2 --
If x1<>x2, issue and error.
Used for on-target compile-time error checking.
: !CSP \ x --
Save the stack pointer in CSP
.
Used for on-target compile-time error checking.
: ?CSP \ --
Issue an error if the stack pointer is not the
same as the value previously stored in CSP.
Used for on-target compile-time error checking.
: ?COMP \ --
Error if not in compile state.
: ?EXEC \ --
Error if not interpreting.
: DO \ C: -- do-sys ; Run: n1|u1 n2|u2 -- ; R: -- loop-sys
Begin a DO ... LOOP
construct. Takes the end-value and
start-value from the data-stack.
: ?DO \ C: -- do-sys ; Run: n1|u1 n2|u2 -- ; R: -- | loop-sys
Compile a DO
which will only begin loop execution if the
loop parameters are not the same. Thus 0 0 ?DO ... LOOP
will not execute the contents of the loop.
: LOOP \ C: do-sys -- ; Run: -- ; R: loop-sys1 -- | loop-sys2
The closing statement of a DO ... LOOP
construct.
Increments the index and terminates when the index crosses
the limit.
: +LOOP \ C: do-sys -- ; Run: n -- ; R: loop-sys1 -- | loop-sys2
As with LOOP
except that you specify the increment on
the data-stack.
: BEGIN \ C: -- dest ; Run: --
Mark the start of a structure of the forms:
BEGIN ... UNTIL/AGAIN
BEGIN ... WHILE ... REPEAT
: AGAIN \ C: dest -- ; Run: --
The end of a BEGIN ... AGAIN
construct which specifies
an infinite loop. )
: UNTIL \ C: dest -- ; Run: x --
Compile code into definition which will jump back to the
matching BEGIN
if the supplied condition flag is
Zero/FALSE.
: WHILE \ C: dest -- orig dest ; Run: x --
Separate the condition test from the loop code in a
BEGIN ... WHILE ... REPEAT
block.
: REPEAT \ C: orig dest -- ; Run: --
Loop back to the conditional dest code in a
BEGIN ... WHILE ... REPEAT
construct. )
: IF \ C: -- orig ; Run: x --
Mark the start of an IF ... [ELSE] ... THEN
conditional
block.
: THEN \ C: orig -- ; Run: --
Mark the end of an IF ... THEN
or IF ... ELSE ... THEN
conditional construct.
: endif \ C: orig -- ; Ru: -- ; synonym for THEN
An alias for THEN
. Note that ANS Forth describes
THEN
not ENDIF
.
: AHEAD \ C: -- orig ; Run: --
Start an unconditional forward branch which will be resolved
later.
: ELSE \ C: orig1 -- orig2 ; Run: --
Begin the failure condition code for an IF
.
: CASE \ C: -- case-sys ; Run: --
Begin a CASE ... ENDCASE
construct. Similar to C's
switch.
: OF \ C: -- of-sys ; Run: x1 x2 -- | x1
Begin conditional block for CASE
, executed when the
switch value is equal to the X2 value placed in TOS.
: ENDOF \ C: case-sys1 of-sys -- case-sys2 ; Run: --
Mark the end of an OF conditional block within a CASE
construct. Compile a jump past the ENDCASE
marker at
the end of the construct.
: ENDCASE \ C: case-sys -- ; Run: x --
Terminate a CASE ... ENDCASE
construct. DROP
s the
switch value from the stack.
: ?OF \ C: -- of-sys ; Run: flag --
Begin conditional block for CASE
, executed when the flag
is true.
: END-CASE \ C: case-sys -- ; Run: --
A Version of ENDCASE
which does not drop the switch
value. Used when the switch value itself is consumed by a
DEFAULT condition.
: NEXTCASE \ C: case-sys -- ; Run: x --
Terminate a CASE ... NEXTCASE
construct. DROP
s the
switch value from the stack and compiles a branch back to the
top of the loop at CASE
.
: RECURSE \ Comp: --
Compile a recursive call to the colon definition containing
RECURSE
itself. Do not use RECURSE
between
DOES>
and ;
. Used in the form:
: foo ... recurse ... ;
to compile a reference to FOO
from inside FOO
.
: ?STACK \ --
Error if stack pointer out of range.
: ?UNDEF \ x --
Word not defined error if x=0.
: POSTPONE \ Comp: "<spaces>name" --
Compile a reference to another word. POSTPONE
can handle
compilation of IMMEDIATE
words which would otherwise be
executed during compilation.
: S" \ Comp: "ccc<quote>" -- ; Run: -- c-addr u
Describe a string. Text is taken up to the next double-quote
character. The address and length of the string are returned.
: C" \ Comp: "ccc<quote>" -- ; Run: -- c-addr
As S"
except the address of a counted string is returned.
: Z" \ Comp: "ccc<quote>" -- ; Run: -- z-addr
As S"
except the address of a zero-terminated string is
returned. This word is only compiled if the run-time action
(Z")
has been compiled.
: #LITERAL \ n1 .... nn n -- ; put in dictionary n1 first
Compile n1..nn as literals so that the same stack order
results when the code executes.
This word will be removed in a future release. INTERNAL.
: LITERAL \ Comp: x -- ; Run: -- x
Compile a literal into the current definition. Usually used
in the form [ <expression ] LITERAL
inside a colon
definition. Note that LITERAL
is IMMEDIATE
.
: 2LITERAL \ Comp: x1 x2 -- ; Run: -- x1 x2
A two cell version of LITERAL
.
: CHAR \ "<spaces>name" -- char
Return the first character of the next token in the input stream.
Usually used to avoid magic numbers in the source code.
: [CHAR] \ Comp: "<spaces>name" -- ; Run: -- char
Compile the first character of the next token in the input stream
as a literal. Usually used to avoid magic numbers in the source
code.
: sliteral \ c-addr u -- ; Run: -- c-addr2 u ; 17.6.1.2212
Compile the string c-addr1/u into the dictionary so that at run time
the identical string c-addr2/u is returned. Note that because of
the use of dynamic strings at compile time the address c-addr2 is
unlikely to be the same as c-addr1.
: [ \ --
Switch compiler into interpreter state.
: ] \ --
Switch compiler into compilation state.
: IMMEDIATE \ --
Mark the last defined word as IMMEDIATE
. Immediate
words will execute whenever encountered regardless of
STATE
.
: ' \ "<spaces>name" -- xt
Find the xt of the next word in the input stream. An error occurs
if the xt cannot be found.
: ['] \ Comp: "<spaces>name" -- ; Run: -- xt
Find the xt of the next word in the input stream, and compile it
as a literal. An error occurs if the xt cannot be found.
: [COMPILE] \ "<spaces>name" --
Compile the next word in the input stream. [COMPILE]
ignores the IMMEDIATE
state of the word. Its operation
is mostly superceded by POSTPONE
.
: ( \ "ccc<paren>" --
Begin an inline comment. All text upto the closing bracket is
ignored.
: \ \ "ccc<eol>" --
Begin a single-line comment. All text up to the end of the line is
ignored.
: ", \ "ccc<quote>" --
Parse text up to the closing quote and compile into the
dictionary at HERE
as a counted string. The end of the
string is aligned.
: .( \ "cc<paren>" --
A documenting comment. Behaves in the same manner as (
except that the enclosed text is written to the console at
compile time.
: ASSIGN \ "<spaces>name" --
A state smart word to get the XT of a word. The source word
is parsed from the input stream. Used as part of an
ASSIGN xxx TO-DO yyy
construct.
: (TO-DO) \ -- ; R: xt -- a-addr'
The run-time action of TO-DO
. It is followed by the
data address of the DEFER
red word at which the xt is
stored.
: TO-DO \ "<spaces>name" --
The second part of the ASSIGN xxx TO-DO yyy
construct.
This word will assign the given XT to be the action of a
DEFER
ed word which is named in the input stream.
: exit \ R: nest-sys -- ; exit current definition
Compile code into the current definition to cause a definition to
terminate. This is the Forth equivalent to inserting an RTS/RET
instruction in the middle of an assembler subroutine.
: ; \ C: colon-sys -- ; Run: -- ; R: nest-sys --
Complete the definition of a new 'colon' word or :NONAME
code block.
: INTERPRET \ --
Process the current input line as if it is text entered at
the keyboard.
: N>R \ xn .. x1 N -- ; R: -- x1 .. xn n
Transfer N items and count to the return stack.
: NR> \ -- xn .. x1 N ; R: x1 .. xn N --
Pull N items and count off the return stack.
: EVALUATE \ i*x c-addr u -- j*x ; interpret the string
Process the supplied string as though it had been entered via the
interpreter.
: .sysprompt \ --
Default action of the deferred word .prompt
.
defer .prompt \ --
The deferred prompt. This is useful for large systems
which need additional debug operations in the prompt, e.g.
floating point packages.
: .throw \ throw# --
Display the throw code. Values of 0 and -1 are ignored.
: QUIT \ -- ; R: i*x --
Empty the return stack, store 0 in SOURCE-ID
, and enter
interpretation state. QUIT
repeatedly ACCEPT
s a
line of input and INTERPRET
s it, with a prompt if
interpreting and ECHOING
is on. Note that any task that
uses QUIT
must initialise 'TIB
, BASE
,
IPVEC
, and OPVEC
.
Because some CPUs, e.g. XScale and ARM9s, have separate instruction and data caches, self-modifying code can cause problems when code is laid down (into the data cache) and then an attempt is made to execute it (the instruction cache will not necessarily contain the code). For this reason a word is provided that will synchronise the caches. This word is CPU specific and may reference code in a CPU and/or hardware specific file.
Synchronisation will usually only be necessary when creating words, constants, variables etc. interactively on the target and then executing them before the code has reached the instruction cache. Only executable code has to be synchronised, not data.
If the word FLUSHCACHE ( -- )
is provided before
kernel62.fth is compiled, it will be executed by the text
interpreter before each line is processed. FLUSHCACHE
is also executed by ;
.
If enabled by the non-zero equate COLDCHAIN?
the cold
start code in COLD
will walk a list and execute the xts
contained in it. The xts must have no stack effect ( -- )
and are added to the list by the phrase:
' <wordname> AtCold
The list is executed in the order in which it was defined so that the last word added is executed last. This was done for compatibility with VFX Forth, which also contains a shutdown chain, in which the last word added is executed first.
If the equate COLDCHAIN?
is not defined in the control
file, a default value of 0 will be defined.
l: ColdChainFirst \ -- addr
Dummy first entry in ColdChain.
variable ColdChain \ -- addr
Holds the address of the last entry in the cold chain.
: AtCold \ xt --
Specifiy a new XT to execute when COLD
is run. Note
that the last word added is executed last. ATCOLD
can
be executed interpretively during cross-compilation. The cold
chain is built in the current CDATA
section.
: WalkColdChain \ -- MPE.0000
Execute all words added to the cold chain. Note that the first
word added is executed first.
At power up, the target executes COLD
or the word specified
by MAKE-TURNKEY <name>
.
: copyRAMtab \ addr --
Copy the given RAM table from Flash into RAM. The table may
initialise multiple blocks of RAM.
: (INIT) \ --
Performs the high level Forth startup. See the source code for
more details.
: COLD \ --
The first high level word executed by default. This word is
set to be the word executed at power up, but this may be
overridden by a later use of MAKE-TURNKEY <name>
. See
the source code for more details of COLD
.
-1 |
ABORT |
-2 |
ABORT" |
-4 |
Stack underflow |
-13 |
Undefined word. |
-14 |
Attempt to interpret a compile only definition. |
-22 |
Control structure mismatch - unbalanced control structure. |
-121 |
Attempt to remove with MARKER or FORGET below FENCE in protected dictionary. |
-403 |
Attempt to compile an interpret only definition. |
-501 |
Error if not LOADing from a block. |
All error handling in the v6.2 kernel is defined in terms of
CATCH
and THROW
. The earlier words ERROR
and
?ERROR
have been removed. If you need them, define them
as synonyms for THROW
and ?THROW
.
The definition of ABORT
has changed significantly. The
old version was:
: ABORT \ i*x -- ; R: j*x --
\ *G Empty the data stack and perform the action of QUIT, which includes
\ ** emptying the return stack, without displaying a message.
xon/xoff off echoing on \ No Xon/Xoff, do Echo
s0 @ sp! \ reset data stack
quit \ start text interpreter
;
The new version is:
: ABORT \ i*x -- ; R: j*x --
\ *G Performs "-1 THROW". This is a compatibility word for earlier
\ ** versions of the kernel. Unfortunately, the earlier versions
\ ** gave problems when ABORT was used in interrupt service routines
\ ** or tasks. The new definition is brutal but consistent.
-1 Throw
;
The old version worked 99% of the time, except that in tasks or
interrupt service routines, the result was unpredictable. Because
modern applications are larger and more complex, ABORT
has to be completely predictable. The line
xon/xoff off echoing on \ No Xon/Xoff, do Echo
is now part of QUIT
. The phrase S0 @ SP!
must now
be provided by the THROW
handler.
The previous definition of THROW
checked for a
previously defined CATCH
and performed the old
ABORT
if no CATCH
had been defined. The new
version assumes that a CATCH
has been defined and
may/will crash if no CATCH
has been performed. The
result is a faster and smaller definition of CATCH
.
However, it is now the programmer's responsibility to provide
a CATCH
handler for ALL ISRs and tasks that may generate
a THROW
. This is actually very little different from
the previous situation, except that the system is less
forgiving if you forget to provide a handler.
Error codes have been made ANS compliant. It is MPE policy that all error and ior (i/o result) codes shall be distinct from now on.
The changes below simplifiy the source code, and permit multiple
tasks to use EVALUATE
without interaction. Note that
compilation from multiple sources/tasks requires the
interpreter/compiler to be interlocked with a semaphore.
The 2VARIABLE SOURCE-STRING
has been removed, and
TO-SOURCE
and SOURCE
use 'TIB
and #TIB
instead.
The state variables ECHOING
and XON/XOFF
are now
USER
variables. In most cases this will have no impact.
However, tasks may now control these variables independently.
QUIT
always enforces ECHOING
on and disables
XON/XOFF processing. QUIT
does not select an I/O device.
This change was made to allow the interpreter to be used on
any channel in systems with several serial lines or with the
Telnet service of the PowerNet TCP/IP stack. Note that any
task that uses QUIT
must initialise IPVEC
,
OPVEC
, ECHOING
and XON/XOFF
.
Removed: ?EMIT
and SOURCE-STRING
.