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 NEXT-USER.
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>"
#64 chars dup +user PAD
Holds the
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 CONTEXT area for search order |
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 BLOCKS? true; for mass storage |
BLK | If BLOCKS? true; user input dev: 0 for keyboard, >0 for block |
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? is 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.
FORTH | Is the standard general purpose vocabulary |
ROOT | This vocabulary stores 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.
|
: 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 frieds to use the given device
for terminal I/O. Compiled for 32 bit systems, but is
also part of LIBRARY.FTH.
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:
|
: 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' ; convert to upper case
If char is in the range 'a' to 'z' convert it to upper case.
Note that this word is language specific and is written to
handle English only.
: 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 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@. |
|
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:
|
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(lsd) to LEFT(msd).
: #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. Returns address
and length of the ascii result.
: -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. By default, the only acceptable
non-numeric character is the double-number separator ','.
: +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 -- value type | 0
Attempt to convert the counted string at 'addr' to an integer.
The return result is either Zero for failed, One for a single-cell
return result (followed by that cell) or Two 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.
: 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
: ?EMIT \ char -- ; emit if echoing enabled
If ECHOING is set, EMIT the character, otherwise
discard it.
: 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.
: $. \ 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 address and length of input source buffer
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.
If it later becomes necessary to discard the saved input, NDROP
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 in input stream, 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 and in winprocs.
: WORD \ char "<chars>ccc<char>" -- c-addr
Similar behaviour to the ANS PARSE definition 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' ; normalise NFA to base of primary CDATA section
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.
: MOVE \ addr1 addr2 u -- ; 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 you specify the increment on the data-stack.
: BEGIN \ C: -- dest ; Run: --
Mark the start of a BEGIN..[while]..UNTIL / AGAIN / [REPEAT]
construct.
: 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 ..ELSE..THEN conditional.
: 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' language 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. DROPs the switch value off
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. DROPs 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.
: (compile) \ -- ; compiles in line xt
The run-time action for COMPILE and friends.
: 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 upto the next double-quote
character. The address and length of the string are returned.
: C" \ Comp: "ccc<quote>" -- ; Run: -- c-addr
As with S" except the address of a counted string is returned.
: #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.
: 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 a
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 addres
of the DEFERred 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 DEFERed 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.
: .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 ACCEPTs a line of
input and INTERPRETs it, with a prompt if interpreting
and ECHOING on. Note that any task that uses QUIT must
initialise 'TIB, BASE, IPVEC, and OPVEC.
Because some CPUs, e.g. StrongARM, have separate instruction and data caches, self-modifying code can cause problems when code is laid down (into the Dcache) and then an attempt is made to execute it (the Icache will not necessarily contain the code). For this reason a word is provided that will synchronise the caches for an address range. 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 got into the Icache. 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>.
: (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.
-4 | Data 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 then as synonyms for THROW and ?THROW.
The definition of ABORT has changed significantly. The old version was:
|
The new version is:
|
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 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 SOURCE-STRING