Copyright Bill Muench All rights reserved.
Permission is granted for non-commercial use, provided this notice is included.
Contact Bill Muench concerning commercial use.

ONLY ALSO FORTH DEFINITIONS

CR .( 8086 eForth ITC 16bit inline model for MS-DOS *** optimized *** )
CR .( Copyright Bill Muench All rights reserved. )

( Bill Muench \ OntoLogic )
(             \ Santa Cruz  CA  95065 )

(        tracks ============================================ )
( 971011 change CURRENT SFIND NAMED? MARKER WORDS )
( 971005 change _[ _] ?STACK only called after EXECUTE )
(        rename DELIMIT PARSE-WORD  add [CHAR] )
( 971003 rename pass _PASS  wake _WAKE  do" _" )
(        rename parse _PARSE  delimit _DELIMIT  do[ _[  do] _] )
(        remove >NAME  change DUMP SSEE )
( 970923 change _DOES> DOES> to use TOKEN and :NONAME )
( 970304 change ALIGNED DEPTH HAT =  add 0= NIP BOUNDS )
( 950717 change ACCEPT TOKEN? to NAMED?  remove CON )
( 950627 change to inline names 16k image )
(        change ALIGNED too slow )
(        change NAME>  SEE  HEAD,  CODE  :  PACK  DP  MARKER  DOES> )
(        rename _IF _ELSE _S" _." _ABORT" _DOES> _MARKER )
(        rename _CON _VAR _USR  ADR> to NAMED? )
(        add /STRING S, SLITERAL )
( 950525 add ALIGN to _DOES> )
( 950511 change QUIT  add 'OK LTOKEN CTOKEN  rename find to SFIND )
( 950410 change D. space at end, SSEE )
( 950322 add TOKEN  fix RECURSE with :NONAME )
( 950321 CONTEXT find WORDLIST ORDER@ GET-ORDER SET-ORDER )
( 941011 STOP TYPE _TYPE DUMP DM+ )
( 941006 2.5.0 )
(        add INITIALIZETARGETIMAGE )
(        add ALIGN to ] MARKER WORDLIST  change PACK _TYPE DM+ )
(        change ' POSTPONE CR ACCEPT BL .ID LEX! does if else )
(        change to linked search order WID? CONTEXT find )
(        REVEAL LAST FORTH-WORDLIST VLINK WORDLIST HEAD, WORDS )
(        GET-ORDER SET-ORDER marker MARKER >NAME ADR> )
( 940817 ITC 1616 )
(        change from CMOVE to MOVE )
(        remove use of CHARS )
(        Environmental dependency: )
(          only two's complement arithmetic supported )
(            ie true flags=-1 and NEGATE )
(          systems with char<byte NOT supported )
( 940815 ITC 3232 32bit tokens )
( 940814 ITC again! )
( 940806 2.4.2 )
(        remove new NEW c" C" )
(        add search order  W- W+ )
(        rename LEX! LIT DOES If Else  BKSP )
(               !lex lit does if else =BKSP )
(        rename <RESOLVE >MARK search-wordlist )
(               RESOLVE  MARK  WID? )
(        change ADR> ALIGNED >MARK DM+ DUMP WORDS HEAD, )
(               find ?UNIQUE marker MARKER QUIT )
( 940523 2.4.1 32bit meta C, )
(        change WORDS USERs BUILD ACTIVATE HAT DEPTH QUIT COLD )
(        replace HLD with HERE in ' POSTPONE  change >MARK )
( 940520 remove END-CODE STRING, CONSTANTs -1 0 1 2 )
( 940519 remove TIB  add SOURCE  change 32bit return stack )
( 940513 add CR to ?UNIQUE )
(        replace HERE with HLD in ' POSTPONE )
( 930811 2.40 )
( 930809 start 32bit eForth with 16bit tokens )
( 930731 ah, postfix again )
( 930719 remove ?STACK from EVALUATE add to _[ and _] )
( 930604 ' saves name address at HERE  add [ to REVEAL )
(        add POSTPONE  remove COMPILE [COMPILE] )
( 930530 add CHAR- CHAR+ CHARS COMPILE,  change ERF to TF )
( 930326 remove use of FOR NEXT AFT )
(        change EVAL to EVALUATE  remove >RESOLVE <MARK )
( 930224 add multitasker )
( 930212 2.30 convert to BTC )
(        add >ADR ADR>  remove QUERY )
( 920326 S.R H# _" _[ _] )
( 920324 replace SHIFT with LSHIFT RSHIFT )
(        replace NOT with INVERT )
( 920219 fix IMMEDIATE COMPILE-ONLY  change [[ to REVEAL dak )
(        new MARKER  QUIT  ALIGN  HEAD, )
( 920205 WORDS  2@ 2!  CR  remove FILE HAND  change FROM )
( 920126 -SAME? SHIFT abort" .OK )
( 920112 seperate _DELIMIT DELIMIT from _PARSE PARSE  STATE )
(        double number output and input  EVAL QUIT )
( 920110 use C@ in _PARSE -SAME? find  ,C"  BKSP dak )
( 911121 PACK STDIN :  remove TOKEN WORD NAME?  add S" )
( 910828 DUMP field size jf )
( 910722 ANS update C" ACCEPT PICK  add DOES> >BODY SM/REM )
( 910719 update : TOKEN WORD  add FROM STDIN stdin :NONAME )
( 910408 accept rid EXPECT add MARKER NEW )
( 910405 ITC update )
( 900707 convert to MASM format )
( 900412 start model meta-compile )
( 89xxxx bForth MS-DOS version )
(        coyote ============================================ )

( Notation )
  ( 0x00      Boot Firmware byte codes )
  ( 0.0.0000  ANS reference numbers )

( Conventions )
  ( a   address )
  ( c   character )
  ( f   flag  0 or non-zero )
  ( n   signed single )
  ( d   signed double )
  ( u   unsigned single )
  ( ud  unsigned double )
  ( xt  execution token )

( Name structure: link\count\name string\attribute )
  ( 'link' pointer to next 'name string' )
  ( 'count' byte length of name string 'nnnn nnnn' )
  (   n - string length, 255 bytes max )
  ( 'name string' variable length ascii 'ccc' )
  (   compiler does not set bits in the 'name string' )
  ( 'attribute' byte compiler flags 'icxx xxxx' )
  (   i - immediate )
  (   c - compile only )
  (   x - reserved )
  ( 0 < la na < ... < la na < last name compiled )

( 8086 register usage )
  ( flags the direction bit must normally be cleared. CLD )
  ( SI    IP Interpreter  Pointer  DS:SI )
  ( BP    RP Return stack Pointer  SS:BP builds up )
  ( SP    SP data Stack   Pointer  SS:SP builds down )
  ( CS=DS=SS  the segment registers must be equal )
  (       or changed temporarily within a code word. )

  ( ES    free )
  ( DI    free  ES:DI )
  ( AX    free )
  ( BX    free )
  ( CX    free )
  ( DX    free )

( ========================================================== )

META[ CR .( Metacompile Begin )

CR .( System equates )

D# 16 EQU #UP ( user variable ) \ ???
D# 64 EQU #RP ( return stack )
D# 64 EQU #SP ( data stack )

D# 80 EQU #TIB ( input buffer size ) ( 6.2.0060 )

D# 80 #BITS D# 2 * D# 2 + MAX ( min [#BITS*2]+2 to format in base2 )
      EQU #PAD ( size above HERE for temporary user buffer )

H# 40 EQU =COMP ( attribute compile-only bit )
H# 80 EQU =IMED ( attribute immediate bit )

D# 8  EQU #VOCS ( vocabulary stack depth )
D# 16 EQU #DUMP ( bytes per line, adjust to display )

D# 13 EQU =CR ( the carrage return character )
D# 10 EQU =LF ( the line feed character )
D# 8  EQU =BS ( the backspace character )
D# 32 EQU =BL ( the blank character )

.( Memory allocation )

( bootdata\dp>-pad>---<u\r>--<s\tib>- )

H# 2000 !IMAGE ( max target image size in bytes )

H# FFFE ALIGNED      ( end of memory, index down )
#TIB CHARS ALIGNED - ( allocate input buffer )
    DUP EQU =TIB     ( terminal input buffer )
    DUP EQU =SP      ( data stack, builds down )
#SP CELLS -          ( allocate data stack, MS-DOS also uses! )
#RP CELLS -          ( allocate return stack )
        EQU =RP      ( return stack, builds up )

( ========================================================== )

.( System entry point )

H# 100 ORG

PROC RESET ( cold start entry )
  D# 0 ## ax mov ( patch with VCOLD )
  ax jmp
END-CODE

LABEL =VERSION
  ,C" eForth ITC16i 971014.1"

LABEL =(C)
  ,C" Copyright Bill Muench All rights reserved."

.( Interpreters )

CODE EXIT ( -- ) ( R: a -- ) ( 6.1.1380 )( 0x33 ) \ ITC
LABEL EXIT1
  D# 0 bp [] si mov    ( unnest )
  D# 1 CELLS ## bp sub ( pop RP )
LABEL NEXT1            ( label for next, )
  lods                 ( next token )
  ax di mov  D# 0 di [] jmp ( new interpreter )
END-CODE

PROC LIST1          ( entry for : words ) \ ITC
  D# 1 CELLS ## bp add ( push RP )
  si D# 0 bp [] mov    ( nest )
  D# 1 CELLS ## di add
  di si mov  next,     ( new list )
END-CODE

CODE EXECUTE ( xt -- ) ( 6.1.1370 )( 0x1D ) \ ITC
  di pop  D# 0 di [] jmp
END-CODE

CODE _LIT ( -- n ) ( 0x10 )
  lods  ax push  next,
END-CODE COMPILE-ONLY

.( Branch )

CODE _ELSE ( -- ) ( 0x13 )
  D# 0 si [] si mov  next, ( absolute branch )
END-CODE COMPILE-ONLY

CODE _IF ( f -- ) ( 0x14 )
  bx pop  bx bx or
  z= if ( branch if f=0 )
    D# 0 si [] si mov  next, ( absolute branch )
  then  D# 1 CELLS ## si add  next, ( continue )
END-CODE COMPILE-ONLY

.( Memory read & write )

CODE C! ( c a -- ) ( 6.1.0850 )( 0x75 )
  bx pop  ax pop  al D# 0 bx [] mov  next,
END-CODE

CODE C@ ( a -- c ) ( 6.1.0870 )( 0x71 )
  bx pop  ax ax xor  D# 0 bx [] al mov  ax push  next,
END-CODE

CODE ! ( n a -- ) ( 6.1.0010 )( 0x72 )
  bx pop  D# 0 bx [] pop  next,
END-CODE

CODE @ ( a -- n ) ( 6.1.0650 )( 0x6D )
  bx pop  D# 0 bx [] push  next,
END-CODE

.( Return stack )

CODE RP@ ( -- a )
  bp push  next,
END-CODE

CODE RP! ( a -- )
  bp pop  next,
END-CODE COMPILE-ONLY

CODE >R ( n -- ) ( R: -- n ) ( 6.1.0580 )( 0x30 )
  D# 1 CELLS ## bp add  D# 0 bp [] pop  next,
END-CODE COMPILE-ONLY

CODE R@ ( -- n ) ( R: n -- n ) ( 6.1.2070 )( 0x32 )
  D# 0 bp [] push  next,
END-CODE

CODE R> ( -- n ) ( R: n -- ) ( 6.1.2060 )( 0x31 )
  D# 0 bp [] push  D# 1 CELLS ## bp sub  next,
END-CODE COMPILE-ONLY

.( Data stack )

CODE SP@ ( -- a )
  sp bx mov  bx push  next,
END-CODE

CODE SP! ( a -- )
  sp pop  next,
END-CODE

CODE DROP ( n -- ) ( 6.1.1260 )( 0x46 )
  bx pop  next,
END-CODE

CODE SWAP ( n1 n2 -- n2 n1 ) ( 6.1.2260 )( 0x49 )
  bx pop  ax pop  bx push  ax push  next,
END-CODE

CODE DUP ( n -- n n ) ( 6.1.1290 )( 0x47 )
  bx pop  bx push  bx push  next,
END-CODE

CODE OVER ( n1 n2 -- n1 n2 n1 ) ( 6.1.1990 )( 0x48 )
  bx pop  ax pop  ax push  bx push  ax push  next,
END-CODE

.( ALU )

CODE 1+ ( n -- n )
  bx pop  bx inc  bx push  next,
END-CODE

CODE 2+ ( n -- n )
  bx pop  bx inc  bx inc  bx push  next,
END-CODE

CODE 1- ( n -- n )
  bx pop  bx dec  bx push  next,
END-CODE

CODE 2- ( n -- n )
  bx pop  bx dec  bx dec  bx push  next,
END-CODE

CODE CHAR- ( a -- a )
  ax pop  D# 1 CHARS ## ax sub  ax push  next,
END-CODE

CODE CHAR+ ( a -- a ) ( 6.1.0897 )( 0x62 )
  ax pop  D# 1 CHARS ## ax add  ax push  next,
END-CODE

CODE CHARS ( n -- n ) ( 6.1.0898 )( 0x66 )
  next,
END-CODE IMMEDIATE

CODE CELL- ( a -- a )
  ax pop  D# 1 CELLS ## ax sub  ax push  next,
END-CODE

CODE CELL+ ( a -- a ) ( 6.1.0880 )( 0x65 )
  ax pop  D# 1 CELLS ## ax add  ax push  next,
END-CODE

CODE CELLS ( n -- n ) ( 6.1.0890 )( 0x69 )
  bx pop  D# 1 ## bx shl  bx push  next,
END-CODE

CODE 0< ( n -- f ) ( 6.1.0250 )( 0x36 )
  ax pop  cwd  dx push  next,
END-CODE

CODE AND ( n n -- n ) ( 6.1.0720 )( 0x23 )
  bx pop  ax pop  ax bx and  bx push  next,
END-CODE

CODE OR ( n n -- n ) ( 6.1.1980 )( 0x24 )
  bx pop  ax pop  ax bx or  bx push  next,
END-CODE

CODE XOR ( n n -- n ) ( 6.1.2490 )( 0x25 )
  bx pop  ax pop  ax bx xor  bx push  next,
END-CODE

CODE UM+ ( u u -- u cy )
  bx pop  ax pop  bx ax add
  D# 0 ## bx mov  bx bx adc
  ax push  bx push  next,
END-CODE

.( System dependent I/O )

( MS-DOS only ============================================== )

CODE REDIRECT ( asciiz -- f )
  dx pop                ( dx=filespec0 )
  H# 3D00 ## ax mov     ( open file read-only )
  H# 21 int
  u< ~ if               ( ?err )
    D# 0 ## cx mov      ( stdin )
    ax bx mov           ( file handle )
    H# 4600 ## ax mov   ( redirect handle )
    H# 21 int           ( file = stdin )
    u< ~ if             ( ?err )
      H# 3E00 ## ax mov ( close file )
      H# 21 int
      u< ~ if           ( ?err )
        ax ax xor       ( no err )
      then
    then
  then ax push  next,   ( error code )
END-CODE COMPILE-ONLY

( ========================================================== )

CODE !IO ( u -- ) ( initialize I/O device )
  bx pop  next, ( nothing to do for MS-DOS )
END-CODE

CODE ?RX ( -- c -1 | 0 )
  bx bx xor          ( BX=0 setup false flag )
  H# FF ## dl mov    ( command == input )
  D# 6 ## ah mov     ( MS-DOS Direct Console I/O )
  H# 21 int
  z= ~ if            ( ?key ready )
    al al or         ( AL=0 if extended code )
    z= if            ( ?extended code )
      H# 21 int      ( AH=6 still )
      al ah mov      ( extended code in msb )
      bl al mov      ( al=0 )
    else bh ah mov   ( ah=0 )
    then
    ax push          ( save character )
    bx dec           ( true flag )
  then  bx push  next,
END-CODE

CODE TX! ( c -- )
  dx pop           ( char in DL )
  D# 2 ## ah mov   ( MS-DOS Character Output )
  H# 21 int  next, ( ^C will terminate )
END-CODE

( ============================================================ )

CODE NOOP ( -- ) ( 0x7B )
  next,
END-CODE

.( System variables )

CODE _VAR ( -- a ) ( 0xB9 )
  si push  EXIT1 jmp
END-CODE COMPILE-ONLY

CODE _CON ( -- n ) ( 0xBA )
  lods  ax push  EXIT1 jmp
END-CODE COMPILE-ONLY

CREATE '?KEY ( input device vector )
  ' ?RX ,
CREATE 'EMIT ( output device vector )
  ' TX! ,

VARIABLE BASE ( numeric radix ) ( 6.1.0750 )( 0xA0 )
VARIABLE DPL  ( numeric input decimal place )
VARIABLE HLD  ( numeric output string pointer )

VARIABLE >IN ( input buffer offset ) ( 6.1.0560 )
CREATE #IN   ( input buffer count )
  D# 2 CELLS ALLOT ( input buffer address )

VARIABLE CSP ( save stack pointer )

CREATE STATE ( interpret/compile flag ) ( 6.1.2250 )( 0xDC )
  D# 2 CELLS ALLOT ( interpret/compile vector )

CREATE DP ( dictionary pointer )
  D# 2 CELLS ALLOT

CREATE SUP ( -- tid )
  =RP , ( return stack )
  =SP , ( data stack )

=BL CONSTANT BL ( -- c ) ( 6.1.0770 )( 0xA9 )

.( Common functions )

: HEX ( -- ) ( 6.2.1660 ) D# 16 BASE ! ;
: DECIMAL ( -- ) ( 6.1.1170 ) D# 10 BASE ! ;

CODE ROT ( n1 n2 n3 -- n2 n3 n1 ) ( 6.1.2160 )( 0x4A )
  bx pop  dx pop  ax pop  dx push  bx push  ax push  next,
END-CODE

CODE NIP ( n1 n2 -- n2 ) ( 6.2.1930 )( 0x4D )
  bx pop  sp inc  sp inc  bx push  next,
END-CODE

CODE 2DROP ( n n -- ) ( 6.1.0370 )( 0x52 )
  D# 2 CELLS ## sp add  next,
END-CODE

CODE 2DUP ( n1 n2 -- n1 n2 n1 n2 ) ( 6.1.0380 )( 0x53 )
  sp di mov  D# 0 di [] bx les  es push  bx push  next,
END-CODE

CODE ?DUP ( n -- n n | 0 ) ( 6.1.0630 )( 0x50 )
  cx pop  cx? if  cx push  then  cx push  next,
END-CODE

CODE + ( n n -- n ) ( 6.1.0120 )( 0x1E )
  bx pop  ax pop  ax bx add  bx push  next,
END-CODE

CODE D+ ( d d -- d ) ( 8.6.1.1040 )( 0xD8 )
  dx pop  ax pop
  bx pop  cx pop  cx ax add  bx dx adc  ax push  dx push  next,
END-CODE

CODE INVERT ( n -- n ) ( 6.1.1720 )( 0x26 )
  bx pop  bx not  bx push  next,
END-CODE

CODE NEGATE ( n -- n ) ( 6.1.1910 )( 0x2C )
  bx pop  bx neg  bx push  next,
END-CODE

CODE S>D ( n -- d ) ( 6.1.2170 )
  ax pop  cwd  ax push  dx push  next,
END-CODE

CODE ABS ( n -- u ) ( 6.1.0690 )( 0x2D )
  ax pop  cwd  dx ax xor  dx ax sub  ax push  next,
END-CODE

CODE DNEGATE ( d -- d ) ( 8.6.1.1230 )
  bx pop
LABEL DNEG1
  ax pop  bx neg  ax neg  D# 0 ## bx sbb  ax push  bx push  next,
END-CODE

CODE DABS ( d -- ud ) ( 8.6.1.1160 )
  bx pop  bx bx or  DNEG1 z< ~ until  bx push  next,
END-CODE

CODE - ( n n -- n ) ( 6.1.0160 )( 0x1F )
  bx pop  ax pop  bx ax sub  ax push  next,
END-CODE

CODE PICK ( n -- n ) ( 6.2.2030 )( 0x50 )
  bx pop  D# 1 ## bx shl  sp bx add  D# 0 bx [] push  next,
END-CODE

.( Comparison )

CODE 0= ( n -- f ) ( 6.1.0270 )( 0x34 )
  ax pop  D# 1 ## ax sub  ax ax sbb  ax push  next,
END-CODE

CODE = ( n n -- f ) ( 6.1.0530 )( 0x3C )
  bx pop  ax pop  bx ax sub  D# 1 ## ax sub  bx bx sbb  bx push  next,
END-CODE

CODE U< ( u u -- f ) ( 6.1.2340 )( 0x40 )
  bx pop  cx pop  bx cx sub  bx bx sbb  bx push  next,
END-CODE

CODE -1 ( -- -1 )
LABEL YEA
  D# -1 ## bx mov  bx push  next,
END-CODE

CODE < ( n n -- f ) ( 6.1.0480 )( 0x3A )
  bx pop  ax pop  bx ax cmp  YEA s< ~ until
  bx bx xor
LABEL PUSH1
  bx push  next,
END-CODE

CODE MIN ( n n -- n ) ( 6.1.1880 )( 0x2E )
  bx pop  ax pop  bx ax cmp  PUSH1 s> ~ until
LABEL MIN1
  ax push  next,
END-CODE

CODE MAX ( n n -- n ) ( 6.1.1870 )( 0x2F )
  bx pop  ax pop  bx ax cmp  MIN1 s> ~ until
  bx push  next,
END-CODE

CODE WITHIN ( u ul uh -- f ) ( 6.2.2440 )( 0x45 )
  bx pop  cx pop  cx bx sub  dx pop
  cx dx sub  bx dx sub  bx bx sbb  bx push  next,
END-CODE

.( Multiply )

CODE LSHIFT ( u n -- u ) ( 6.1.1805 )( 0x27 )
  cx pop  bx pop  cl bx shl  bx push  next,
END-CODE

CODE UM* ( u u -- ud ) ( 6.1.2360 )( 0xD4 )
  bx pop  ax pop  bx mul  ax push  dx push  next,
END-CODE

CODE * ( n n -- n ) ( 6.1.0090 )( 0x20 )
  bx pop  ax pop  bx mul  ax push  next,
END-CODE

.( Divide )

CODE RSHIFT ( u n -- u ) ( 6.1.2162 )( 0x28 )
  cx pop  bx pop  cl bx shr  bx push  next,
END-CODE

CODE UM/MOD ( ud u -- ur uq ) ( 6.1.2370 )( 0xD5 )
  bx pop  dx pop  ax pop  bx div  dx push  ax push  next,
END-CODE

CODE SM/REM ( d n -- r q ) ( 6.1.2214 ) ( symmetric )
  bx pop  dx pop  ax pop  bx idiv  dx push  ax push  next,
END-CODE

CODE FM/MOD ( d n -- r q ) ( 6.1.1561 ) ( floored )
  bx pop  dx pop  ax pop
  bx idiv  dx cx mov  bx dx xor ( ?sign )
  z< ~ if ( same sign most often )
    cx push  ax push  next,
  then
  cx? if ( remainder 0<> most often )
    ax dec  bx cx add
  then  cx push  ax push  next,
END-CODE

: /MOD ( n n -- r q ) ( 6.1.0240 )( 0x2A )
  OVER 0< SWAP  FM/MOD ; ( or SM/REM )

: MOD ( n n -- r ) ( 6.1.1890 )( 0x22 ) /MOD DROP ;
: / ( n n -- q ) ( 6.1.0230 )( 0x21 ) /MOD NIP ;

.( Memory access )

CODE +! ( n a -- ) ( 6.1.0130 )( 0x6C )
  bx pop  ax pop  ax D# 0 bx [] add  next,
END-CODE

CODE COUNT ( a -- a c ) ( 6.1.0980 )( 0x84 )
  bx pop  ax ax xor  D# 0 bx [] al mov  bx inc  bx push  ax push  next,
END-CODE

CODE BOUNDS ( a n -- a+n a ) ( 0xAC )
  dx pop  ax pop  ax dx add  dx push  ax push  next,
END-CODE

CODE /STRING ( a u n -- a+n u-n ) ( 17.6.1.0245 )
  ax pop  bx pop  cx pop  ax cx add  cx push  ax bx sub  bx push  next,
END-CODE

CODE ALIGNED ( a -- a ) ( 6.1.0706 )( 0xAE )
  ax pop  D# 1 CELLS D# 1 - DUP ## ax add  INVERT ## ax and  ax push  next,
END-CODE

CODE 2! ( u u a -- ) ( 6.1.0310 )( 0x77 )
  bx pop  D# 0 bx [] pop  D# 2 bx [] pop  next,
END-CODE

CODE 2@ ( a -- u u ) ( 6.1.0350 )( 0x76 )
  bx pop  D# 0 bx [] ax les  es push  ax push  next,
END-CODE

CODE MOVE ( a a u -- ) ( 6.1.1900 )( 0x78 )
  si bx mov  cs ax mov  ax es mov  cx pop  di pop  si pop
  si di cmp  u< if
    repz  byte movs
  else
    cx dec  cx di add  cx si add  cx inc
    std  repz  byte movs  cld
  then  bx si mov  next,
END-CODE

CODE FILL ( a u c -- ) ( 6.1.1540 )( 0x79 )
  cs ax mov  ax es mov  ax pop  cx pop  di pop  repz  byte stos  next,
END-CODE

CODE -TRAILING ( a u -- a u ) ( 17.6.1.0170 )
  cx pop  di pop  di push  cx di add  di dec
  cs ax mov  ax es mov  =BL ## al mov  std
  begin  byte scas
  u< ~ while ( white space ? )
  cx? ~ until then  cld  cx push  next,
END-CODE

CODE >ADR ( xt -- a ) \ ITC
  next,
END-CODE IMMEDIATE
CODE >BODY ( xt -- a ) ( 6.1.0550 )( 0x86 ) \ ITC
  ax pop  D# 2 CELLS ## ax add  ax push  next,
END-CODE

.( Numeric input )

CODE 0 ( -- 0 )
LABEL FAIL
  bx bx xor  bx push  next,
END-CODE

CODE DIGIT? ( c base -- u f ) ( 0xA3 )
  bx pop  ax pop  ax push  CHAR 0 ## al sub  FAIL u< ~ until  D# 9 ## al cmp
  s> if  D# 17 ## al cmp  FAIL u< ~ until  D# 7 ## al sub
  then  bl al cmp  FAIL u< until
  al bl mov  ax pop  D# -1 ## ax mov  bx push  ax push  next,
END-CODE

: >NUMBER ( ud a u -- ud a u ) ( 6.1.0570 )
  BEGIN DUP
  WHILE >R  DUP >R C@ BASE @ DIGIT?
  WHILE SWAP BASE @ UM* DROP ROT BASE @ UM* D+ R> CHAR+ R> 1-
  REPEAT DROP R> R> THEN ;

: NUMBER? ( a u -- d -1 | a u 0 )
  OVER C@ [CHAR] - = DUP >R IF D# 1 /STRING THEN
  >R >R  0 DUP  R> R>  -1 DPL !
  BEGIN >NUMBER DUP
  WHILE OVER C@ [CHAR] . XOR
    IF ROT DROP ROT R> 2DROP  0 EXIT
    THEN 1- DPL !  CHAR+  DPL @
  REPEAT 2DROP R> IF DNEGATE THEN -1 ;

.( Multitask )

VARIABLE UP ( current task pointer )

CODE _USR ( -- a )
  lods  UP ax add  ax push  EXIT1 jmp
END-CODE COMPILE-ONLY

( U1\TF\TID\TOS\STATUS\FOLLOWER\r>--<s  order IS important )
  D# 1 CELLS ( init offset )
  CELL- DUP USER FOLLOWER ( address of next task's STATUS )
  CELL- DUP USER STATUS   ( PASS or WAKE )
  CELL- DUP USER TOS      ( top of stack )
  CELL- DUP USER TID      ( back link tid )
  CELL- DUP USER TF       ( throw frame )
  CELL- DUP USER U1       ( free )
DROP ( cleanup )

: 'S ( tid a -- a ) ( index another task's local variable )
  FOLLOWER  CELL+ - SWAP @ + ;

' _ELSE CONSTANT PASS ( absolute branch )

: _WAKE ( -- ) ( restore follower ) \ ???code
  R> UP !  TOS @ SP! RP! ; COMPILE-ONLY
' _WAKE CONSTANT WAKE

: PAUSE ( -- ) ( allow another task to execute ) \ ???code
  RP@  SP@ TOS !  FOLLOWER @ >R ;

: STOP ( -- ) ( sleep current task )
  PASS STATUS ! PAUSE ; COMPILE-ONLY

: GET ( semaphore -- )
  PAUSE ( remember your manners )
  DUP @ STATUS XOR ( owner ? )
  IF BEGIN DUP @ WHILE PAUSE REPEAT ( no, wait for release )
    STATUS SWAP ! ( lock ) EXIT
  THEN DROP ;

: RELEASE ( semaphore -- )
  DUP @ STATUS XOR IF DROP EXIT THEN  0 SWAP ! ( unlock ) ;

: SLEEP ( tid -- ) ( sleep another task )
  PASS SWAP STATUS 'S ! ;

: AWAKE ( tid -- ) ( wake another task )
  WAKE SWAP STATUS 'S ! ;

: ACTIVATE ( tid -- )
  DUP 2@        ( tid sp rp )
  R> OVER !     ( save entry at rp )
  OVER !        ( save rp at sp )
  OVER TOS 'S ! ( save sp in tos )
  AWAKE ; COMPILE-ONLY

: BUILD ( tid -- )
  DUP SLEEP                     ( sleep new task )
  FOLLOWER @ OVER FOLLOWER 'S ! ( link new task )
  DUP STATUS 'S FOLLOWER !      ( link old task )
  DUP TID 'S ! ;                ( link to tid )

.( Numeric output )

CODE HERE ( -- a ) ( 6.1.1650 )( 0xAD )
  DP push  next,
END-CODE

CODE PAD ( -- a ) ( 6.2.2000 )
  DP ax mov  #PAD CHARS ## ax add  ax push  next,
END-CODE

: <# ( -- ) ( 6.1.0490 )( 0x96 ) PAD HLD ! ;

CODE DIGIT ( u -- c )
  ax pop  D# 9 ## ax cmp  s> if  D# 7 ## ax add  then
  CHAR 0 ## ax add   ax push  next,
END-CODE

: HOLD ( c -- ) ( 6.1.1670 )( 0x95 ) HLD @ CHAR- DUP HLD ! C! ;

: # ( d -- d ) ( 6.1.0030 )( 0xC7 )
  0 BASE @ UM/MOD >R BASE @ UM/MOD SWAP DIGIT HOLD R> ;

: #S ( d -- d ) ( 6.1.0050 )( 0xC8 ) BEGIN # 2DUP OR 0= UNTIL ;
: #> ( d -- a u ) ( 6.1.0040 )( 0xC9 ) 2DROP HLD @ PAD OVER - ;

: SIGN ( n -- ) ( 6.1.2210 )( 0x98 ) 0< IF [CHAR] - HOLD THEN ;

.( Error handling )

: CATCH ( xt -- 0 | err ) ( 9.6.1.0875 )( 0x217 )
  SP@ >R  TF @ >R  RP@ TF !  EXECUTE  R> TF !  R> DROP  0 ;

: THROW ( 0 | err -- | err ) ( R: i*x i*y -- i*x i*y | i*x ) ( 9.6.1.2275 )( 0x218 )
  ?DUP IF TF @ RP!  R> TF !  R> SWAP >R SP! DROP R> THEN ;

: ABORT ( i*n -- ) ( R: i*x i*y -- i*x ) ( 9.6.2.0670 )( 0x216 ) -1 THROW ;

.( Basic I/O )

: ?KEY ( -- c -1 | 0 )  PAUSE  '?KEY @ EXECUTE ;
: KEY ( -- c ) ( 6.1.1750 )( 0x8E ) BEGIN ?KEY UNTIL ;
: NUF? ( -- f ) ?KEY DUP IF 2DROP KEY [ =CR ] LITERAL = THEN ;

: EMIT ( c -- ) ( 6.1.1320 )( 0x8F ) 'EMIT @ EXECUTE ;
: SPACE ( -- ) ( 6.1.2220 ) BL EMIT ; ,C" coyote"

: EMITS ( n c -- )
  SWAP 0 MAX BEGIN DUP WHILE OVER EMIT 1- REPEAT 2DROP ;
: SPACES ( n -- ) ( 6.1.2230 ) BL EMITS ;

: TYPE ( a u -- ) ( 6.1.2310 )( 0x90 )
  CHARS BOUNDS BEGIN 2DUP XOR WHILE COUNT EMIT REPEAT 2DROP ;
: CR ( -- ) ( 6.1.0990 )( 0x92 ) [ =CR ] LITERAL EMIT [ =LF ] LITERAL EMIT ;

: _" ( -- a )
  R> R> DUP COUNT CHARS + ALIGNED >R SWAP >R ; COMPILE-ONLY

: _S" ( -- a u ) _" COUNT ; COMPILE-ONLY
: _." ( -- ) ( 0x12 ) _" COUNT TYPE ; COMPILE-ONLY
: _ABORT" ( i*n f -- i*n | ) ( R: i*x i*y -- i*x i*y | i*x )
  IF _" CSP ! D# -2 THROW THEN _" DROP ; COMPILE-ONLY

: S.R ( a u n -- ) OVER - SPACES TYPE ;
: D.R ( d n -- ) ( 8.6.1.1070 ) >R DUP >R DABS <# #S R> SIGN #> R> S.R ;
: U.R ( u n -- ) ( 6.2.2330 )( 0x9C ) 0 SWAP D.R ;
: .R ( n n -- ) ( 6.2.0210 )( 0x9E ) >R S>D R> D.R ;

: D. ( d -- ) ( 8.6.1.1060 ) 0 D.R SPACE ;
: U. ( u -- ) ( 6.1.2320 )( 0x9B ) 0 D. ;
: . ( n -- ) ( 6.1.0180 )( 0x9D ) BASE @ D# 10 XOR IF U. EXIT THEN S>D D. ;
: ? ( a -- ) ( 15.6.1.0600 ) @ . ;

.( Bits & Bytes )

: PACK ( a1 u a2 -- a2 ) ( 0x83 )
  OVER D# 256 U<
  IF DUP >R  OVER >R  CHAR+ SWAP CHARS MOVE  R> R@ C!  R> EXIT
  THEN D# -18 THROW ;

CODE DEPTH ( -- n ) ( 6.1.1200 )( 0x51 )
  UP di mov  TID di [] bx mov  D# 1 CELLS bx [] bx mov
  sp bx sub  D# 1 ## bx sar  bx push  next,
END-CODE

: ?STACK ( -- ) DEPTH 0< ABORT" depth?" ;

.( Terminal )

: ACCEPT ( a u -- u ) ( 6.1.0695 )
  OVER + OVER ( bot eot cur )
  BEGIN KEY
    DUP [ =CR ] LITERAL XOR ( carrage return ? )
  WHILE
    DUP [ =BS ] LITERAL = ( backspace ? )
    IF ( destructive backspace )
      DROP  >R OVER R@ < DUP ( any chars ? )
      IF [ =BS ] LITERAL DUP EMIT  BL EMIT  EMIT
      THEN R> +
    ELSE ( printable )
      >R  2DUP XOR ( more ? )
      IF R@ OVER C!  CHAR+  R@ EMIT
      THEN R> DROP
    THEN
  REPEAT DROP  NIP  SWAP - ;

.( Interpreter )

CODE SAME? ( a a u -- f )
  si bx mov  cs ax mov  ax es mov
  cx pop  di pop  si pop
  cx? if  repz  byte cmps  z= ~ if  D# 1 ## cx mov  then
  then  cx dec  cx push  bx si mov  next,
END-CODE

: _DELIMIT ( a u -- a u delta ) \ ???chars
  BOUNDS  DUP >R  CHAR-
  BEGIN CHAR+  2DUP XOR ( skip leading BL )
  WHILE BL OVER C@ <
  UNTIL SWAP OVER ( save first non blank addr )
    BEGIN CHAR+  2DUP XOR ( scan trailing BL )
    WHILE DUP C@  BL 1+  <
    UNTIL NIP  DUP CHAR+ ( found )
    ELSE DROP DUP ( not found )
    THEN >R  OVER -  R>
  ELSE DROP 0 OVER ( all BL )
  THEN R> - ;

: _PARSE ( a1 u1 c -- a1 u2 delta ) \ ???chars
  >R  OVER +  OVER CHAR- ( save char, adjust addr )
  BEGIN CHAR+  2DUP XOR ( inc addr ? )
  WHILE DUP C@ R@ = ( match ? )
  UNTIL SWAP R> 2DROP  OVER -  DUP 1+ EXIT ( found )
  THEN  SWAP R> 2DROP  OVER -  DUP ; ( not found )

: NAME> ( a -- xt ) COUNT CHARS + CHAR+ ALIGNED ;

: WID? ( a u wid -- xt lex -1 | a u 0 ) \ ???chars
  SWAP >R  @ ( address of last word )
  BEGIN DUP ( last word ? )
  WHILE COUNT R@ = ( count ? )
    IF 2DUP R@ SAME? ( match )
      IF SWAP R> 2DROP CHAR-
        DUP NAME>  SWAP COUNT CHARS + C@  -1 EXIT ( found )
      THEN
    THEN CHAR-  CELL- @ ( link )
  REPEAT DROP R>  0 ; ( no match )

CREATE CONTEXT ( search order )
  #VOCS D# 1 + CELLS ALLOT ( wids )

: SFIND ( a u -- xt lex -1 | a u 0 )
  CONTEXT CELL- >R ( setup )
  BEGIN R> CELL+ DUP >R @ DUP ( wid | 0 )
  WHILE WID? ( found ? )
  UNTIL -1 THEN R> DROP ;

: _[ ( a u -- ) ( the Forth interpreter )
  SFIND ( search dictionary )
  IF [ =COMP ] LITERAL AND ABORT" compile?"
    EXECUTE ?STACK EXIT
  THEN
  NUMBER? ( unknown symbol, try to convert a number )
  IF DPL @ 0< ( single? )
    IF DROP THEN EXIT
  THEN D# -13 THROW ; COMPILE-ONLY
: [ ( -- ) ( 6.1.2500 ) ['] _[ 0 STATE 2! ; IMMEDIATE

: SOURCE ( -- a u ) ( 6.1.2216 ) #IN 2@ ;
: PARSE-WORD ( "ccc" -- a u ) SOURCE >IN @ /STRING _DELIMIT >IN +! ;

: EVALUATE ( a u -- ) ( 6.1.1360 )( 0xCD )
  >IN @ >R  0 >IN !  SOURCE >R >R  #IN 2!
  BEGIN PARSE-WORD DUP
  WHILE STATE CELL+ @ EXECUTE
  REPEAT 2DROP  R> R> #IN 2!  R> >IN ! ;

( redirect input MS-DOS only =============================== )

: ASCIIZ ( a u a -- a )
  DUP >R  SWAP CHARS  2DUP + 0 SWAP C!  MOVE  R> ;

: STDIN ( a u -- )
  HERE ASCIIZ REDIRECT ABORT" file?" ; COMPILE-ONLY

: FROM ( "ccc" -- ) ( chain not nest )
  PARSE-WORD STDIN  SOURCE >IN ! DROP ;

( ========================================================== )

CREATE 'OK ( prompt options )
  ' NOOP , ( typically .S )
: QUIT ( -- ) ( R: i*x -- ) ( 6.1.2050 )
  SUP @ RP!         ( reset return stack )
  [ ' [ COMPILE, ]  ( reset interpret state )
  S" CON" STDIN     ( reset console i/o, MS-DOS only )
  BEGIN
    BEGIN
      [ =TIB ] LITERAL       ( input buffer )
      DUP [ #TIB ] LITERAL ACCEPT SPACE ( user input )
      ['] EVALUATE CATCH DUP ( error ? )
      IF DUP -1 XOR          ( ABORT  = -1 )
        IF CR DUP D# -2 XOR  ( ABORT" = -2 )
          IF SOURCE DROP     ( undefined error )
            >IN @ -TRAILING TYPE ."  ?(" 0 .R ." )"
          ELSE CSP @ COUNT TYPE
          THEN SPACE
        THEN
        SUP CELL+ @ SP! ( reset data stack )
        RECURSE         ( restart )
      THEN CR STATE @ = ( 0 from CATCH )
    UNTIL 'OK @ EXECUTE ." ok " ( prompt )
  AGAIN ;

.( Compiler )

: ALIGN ( -- ) ( 6.1.0705 ) HERE ALIGNED DP ! ;

: ALLOT ( n -- ) ( 6.1.0710 ) DP +! ;
: S, ( a u -- ) HERE  OVER CHARS CHAR+ ALLOT  PACK DROP ;
: C, ( n -- ) ( 6.1.0860 )( 0xD0 ) HERE  [ D# 1 CHARS ] LITERAL ALLOT  C! ;
: , ( n -- ) ( 6.1.0150 )( 0xD3 ) HERE  [ D# 1 CELLS ] LITERAL ALLOT  ! ;

: COMPILE, ( xt -- ) ( 6.2.0945 )( 0xDD ) , ;
: LITERAL ( n -- ) ( 6.1.1780 ) ['] _LIT COMPILE, , ; IMMEDIATE

: CHAR ( "ccc" -- c ) ( 6.1.0895 ) PARSE-WORD DROP C@ ;
: [CHAR] ( "ccc" -- ) ( 6.1.2520 ) CHAR  [ ' LITERAL COMPILE, ] ; IMMEDIATE

: ' ( "name" -- xt ) ( 6.1.0070 ) PARSE-WORD SFIND IF DROP EXIT THEN D# -13 THROW ;
: ['] ( "name" -- ) ( 6.1.2510 ) '  [ ' LITERAL COMPILE, ] ; IMMEDIATE

: PARSE ( c "ccc" -- a u ) ( 6.2.2008 ) \ ???move
  >R SOURCE >IN @ /STRING R> _PARSE >IN +! ;

: .( ( "comment" -- ) ( 6.2.0200 ) [CHAR] ) PARSE TYPE ; IMMEDIATE
: ( ( "comment" -- ) ( 6.1.0080 ) [CHAR] ) PARSE 2DROP ; IMMEDIATE
: \ ( "comment" -- ) ( 6.2.2535 ) SOURCE >IN ! DROP ; IMMEDIATE

: SLITERAL ( a u -- ) ( -- a u ) ( 17.6.1.2212 )
  ['] _S" COMPILE, S, ALIGN ; IMMEDIATE COMPILE-ONLY

: ,C" ( "ccc" -- ) [CHAR] " PARSE S, ALIGN ;

: S" ( "ccc" -- ) ( 6.1.2165 ) ['] _S" COMPILE, ,C" ; IMMEDIATE COMPILE-ONLY
: ." ( "ccc" -- ) ( 6.1.0190 ) ['] _." COMPILE, ,C" ; IMMEDIATE COMPILE-ONLY

: ABORT" ( "ccc" -- ) ( 6.1.0680 )
  ['] _ABORT" COMPILE, ,C" ; IMMEDIATE COMPILE-ONLY

: _] ( a u -- ) ( the Forth compiler )
  SFIND ( search dictionary )
  IF [ =IMED ] LITERAL AND
    IF EXECUTE ?STACK EXIT ( immediate )
    THEN COMPILE, EXIT
  THEN
  NUMBER? ( unknown symbol, try to convert a number )
  IF DPL @ 0<
    IF DROP ( single )
    ELSE SWAP  [ ' LITERAL COMPILE, ] ( double )
    THEN  [ ' LITERAL COMPILE, ] EXIT
  THEN D# -13 THROW ; COMPILE-ONLY
: ] ( -- ) ( 6.1.2540 ) ALIGN ['] _] -1 STATE 2! ;

CREATE FORTH-WORDLIST ( -- wid ) ( 16.6.1.1595 )
  D# 0 , ( na, of last definition, linked )
  D# 0 , ( wid|0, next or last wordlist in chain )
  D# 0 , ( na, wordlist name pointer )

CREATE LAST ( -- a )
  D# 1 CELLS ALLOT ( na, of last definition, unlinked )
  D# 1 CELLS ALLOT ( wid, current wordlist for linking )
LABEL =TOKEN
  D# 1 CELLS ALLOT ( xt, of last definition )

CREATE CURRENT ( -- a )
  FORTH-WORDLIST , ( wid, new definitions )
  FORTH-WORDLIST , ( wid, head of chain )

: GET-CURRENT ( -- wid ) ( 16.6.1.1643 ) CURRENT @ ;
: SET-CURRENT ( wid -- ) ( 16.6.1.2195 ) CURRENT ! ;
: DEFINITIONS ( -- ) ( 16.6.1.1180 ) CONTEXT @ SET-CURRENT ;

: ?UNIQUE ( a u -- a u )
  2DUP  GET-CURRENT WID?
  IF 2DROP CR ." reDef " 2DUP TYPE EXIT THEN 2DROP ;

: HEAD, ( "name" -- ) \ ???fix ( xt "name" -- )
  PARSE-WORD  DUP
  IF ?UNIQUE ( warn if redefined )
    ALIGN
    GET-CURRENT  DUP @ ,  HERE LAST 2! ( link )
    DUP C, ( save count )
    HERE SWAP  DUP ALLOT  MOVE ( build name )
    0 C, ( build attribute byte )
    EXIT
  THEN D# -16 THROW ; ( attempt to use zero-length string )

| : LEX! ( u -- ) LAST @ COUNT CHARS + DUP >R C@ OR R> C! ;
: IMMEDIATE ( -- ) ( 6.1.1710 ) [ =IMED ] LITERAL  LEX! ;
: COMPILE-ONLY ( -- ) [ =COMP ] LITERAL  LEX! ;

: REVEAL ( -- ) LAST 2@ SWAP ! [ ' [ COMPILE, ] ;
: RECURSE ( -- ) ( 6.1.2120 ) [ =TOKEN ] LITERAL @ COMPILE, ; IMMEDIATE

: POSTPONE ( "name" -- ) ( 6.1.2033 )
  PARSE-WORD SFIND
  IF [ =IMED ] LITERAL AND IF COMPILE, EXIT THEN
    [ ' LITERAL COMPILE, ]  ['] COMPILE, COMPILE,  EXIT
  THEN D# -13 THROW ; IMMEDIATE

.( Defining words )

: CODE ( "name" -- ) ( 15.6.2.0930 ) \ ITC
  HEAD, ALIGN HERE CELL+ , REVEAL ;

: next, ( -- ) \ ITC 80x86 only
  [ NEXT1 ] LITERAL H# E9 C, HERE D# 2 + - , ;

: :NONAME ( -- xt ) ( 6.2.0455 ) \ ITC
  ALIGN HERE  DUP [ =TOKEN ] LITERAL !  [ LIST1 ] LITERAL , ] ;

: : ( "name" -- ) ( 6.1.0450 ) HEAD, :NONAME DROP ;
: ; ( -- ) ( 6.1.0460 ) ['] EXIT COMPILE, REVEAL ; IMMEDIATE COMPILE-ONLY

: _DOES> ( -- ) ( link child )
\  ALIGN ( child ) \ ???why
  R>  [ =TOKEN ] LITERAL @  CELL+ ( ITC )  ! ; COMPILE-ONLY

: DOES> ( -- ) ( 6.1.1250 ) ( build parent )
  ['] _DOES> COMPILE, ( link child )
  :NONAME DROP  ['] R> COMPILE, ( begin child )
; IMMEDIATE COMPILE-ONLY

: CREATE ( "name" -- ) ( 6.1.1000 ) ['] _VAR  : REVEAL COMPILE, ;
: VARIABLE ( "name" -- ) ( 6.1.2410 ) CREATE 0 , ;
: CONSTANT ( n "name" -- ) ( 6.1.0950 ) ['] _CON  : REVEAL COMPILE,  , ;

: USER ( n "name" -- ) ['] _USR  : REVEAL COMPILE,  , ;

: HAT ( u s r "name" -- ) ( -- tid )
  CREATE + SWAP [ D# 7 CELLS ] LITERAL + ( TF\TID\TOS\STATUS\FOLLOWER\r>--<s )
  DUP HERE + ( rp0 ) , + DUP HERE + ( sp0 ) , ALLOT ;

: WORDLIST ( -- wid ) ( 16.6.1.2460 )
  ALIGN HERE 0 ,  DUP CURRENT CELL+  DUP @ ,  !  0 , ;

: ORDER@ ( a -- u*wid u )
  DUP @ DUP IF >R CELL+  RECURSE  R> SWAP 1+ EXIT THEN NIP ;
: GET-ORDER ( -- u*wid u ) ( 16.6.1.1647 ) CONTEXT ORDER@ ;

: SET-ORDER ( u*wid n -- ) ( 16.6.1.2197 )
  DUP -1 = IF DROP FORTH-WORDLIST D# 1 THEN ( default ? )
  [ #VOCS ] LITERAL OVER U< IF D# -46 THROW THEN ( range ? )
  CONTEXT SWAP
  BEGIN DUP
  WHILE >R  SWAP OVER !  CELL+  R> 1-
  REPEAT  ( 0 ) SWAP ! ;

\ ============================================================
: _MARKER ( -- ) ( R: dfa -- ) \ ???
  R> 2@ ( * ) DUP @ FOLLOWER !  DUP CONTEXT
  BEGIN >R CELL+ DUP @ DUP R@ ! WHILE R> CELL+ REPEAT ( search order )
  CELL+ DUP 2@ CURRENT 2!  CELL+ DUP @ ( cur wid & head )
  BEGIN >R  CELL+ DUP @ R@ !  R> CELL+ @ ?DUP 0= UNTIL ( wid last na's )
  R> 2DROP ( * ) DP 2! ; COMPILE-ONLY

: MARKER ( "name" -- ) \ ???
  ALIGN DP 2@ ( * ) FOLLOWER @ ,  CONTEXT
  BEGIN DUP @ DUP , WHILE CELL+ REPEAT  DROP ( search order )
  CURRENT 2@ , DUP , ( cur wid & head )
  BEGIN DUP @ , CELL+ @ ?DUP 0= UNTIL ( wid last na's )
  ['] _MARKER : REVEAL COMPILE, ( * ) , , ;
\ ============================================================

.( Control flow )

: BEGIN ( -- a ) ( 6.1.0760 ) HERE ; IMMEDIATE
: THEN ( a -- ) ( 6.1.2270 ) [ ' BEGIN COMPILE, ] ( OVER - ) SWAP ! ; IMMEDIATE

: RESOLVE ( a -- ) ( [ ' BEGIN COMPILE, ] - ) , ;
: MARK ( -- a ) HERE [ ' BEGIN COMPILE, ] RESOLVE ;

: IF ( -- a ) ( 6.1.1700 ) ['] _IF COMPILE, MARK ; IMMEDIATE
: AHEAD ( -- a ) ( 15.6.2.0702 ) ['] _ELSE COMPILE, MARK ; IMMEDIATE
: ELSE ( a -- a ) ( 6.1.1310 ) [ ' AHEAD COMPILE, ] SWAP [ ' THEN COMPILE, ] ; IMMEDIATE
: WHILE ( a -- a a ) ( 6.1.2430 ) [ ' IF COMPILE, ] SWAP ; IMMEDIATE

: UNTIL ( a -- ) ( 6.1.2390 ) ['] _IF COMPILE, RESOLVE ; IMMEDIATE
: AGAIN ( a -- ) ( 6.2.0700 ) ['] _ELSE COMPILE, RESOLVE ; IMMEDIATE
: REPEAT ( a a -- ) ( 6.1.2140 ) [ ' AGAIN COMPILE, ' THEN COMPILE, ] ; IMMEDIATE

.( Tools )

: .S ( -- ) ( 15.6.1.0220 )( 0x9F )
  ?STACK DEPTH BEGIN ?DUP WHILE DUP PICK . 1- REPEAT ;

CODE !CSP ( -- )
  sp CSP mov  next,
END-CODE

: ?CSP ( -- ) SP@ CSP @ XOR ABORT" csp?" ;

: >CHAR ( c -- c )
  H# 7F AND DUP D# 127 BL WITHIN IF DROP [CHAR] _ THEN ;

: _TYPE ( a u -- ) ( alpha dump )
  CHARS BOUNDS BEGIN 2DUP XOR WHILE COUNT >CHAR EMIT REPEAT 2DROP ;

: _DUMP ( a u -- ) ( numeric dump )
  CHARS BOUNDS BEGIN 2DUP XOR WHILE COUNT D# 3 U.R REPEAT 2DROP ;

: DUMP ( a u -- ) ( 15.6.1.1280 )
  BASE @ >R HEX  CHARS BOUNDS
  BEGIN 2DUP SWAP U< WHILE ( range? )
    CR DUP 0 <#  # # # #  #> TYPE ( address )
    SPACE [ #DUMP ] LITERAL  2DUP _DUMP ( numeric )
    SPACE SPACE  2DUP _TYPE ( alpha )
    CHARS +  NUF? ( user? )
  UNTIL THEN 2DROP  R> BASE ! ;

: .ID ( a -- ) COUNT _TYPE ;

: WIDWORDS ( a u wid -- a u )
  SWAP >R  DUP
  IF CR DUP ." wid=" U. CR
    BEGIN @ DUP ( last name ? )
    WHILE 2DUP CHAR+ R@ SAME? ( match ? )
      IF DUP .ID SPACE THEN CELL-  NUF?
    UNTIL THEN
  THEN DROP R> ;
: WORDS ( "ccc" -- )
  BL PARSE  DUP
  IF CURRENT BEGIN CELL+ @ ?DUP WHILE DUP >R WIDWORDS R> REPEAT ( all wid )
  ELSE CONTEXT @ WIDWORDS
  THEN 2DROP ;

: NAMED? ( aa -- na | 0 )
  CURRENT ( all wid )
  BEGIN CELL+ @ DUP ( last link ? )
  WHILE DUP >R
    BEGIN @ ?DUP ( zero link ? )
    WHILE 2DUP NAME> >ADR = ( match ? )
       IF SWAP R> 2DROP EXIT ( found )
       THEN CELL-
    REPEAT R>
  REPEAT NIP ( not found ) ;

: SSEE ( a u -- ) ( simple decompiler )
  CELLS BOUNDS
  BEGIN 2DUP XOR ( done? )
  WHILE DUP NAMED? ?DUP IF CR .ID CR THEN
    SPACE DUP @ >ADR NAMED? ?DUP
    IF .ID ( display named token )
    ELSE DUP @ 0 U.R ( unnamed token )
    THEN CELL+  NUF?
  UNTIL THEN 2DROP ;
: SEE ( "name" -- ) ( 15.6.1.2194 ) ' >ADR -1 SSEE ;

.( Software reset )

: COLD ( -- )
  SUP 2@ RP! SP! ( init stacks )
  SUP @ CELL- ( FOLLOWER ) UP ! ( init user pointer )
  STATUS FOLLOWER !  SUP TID !  SUP AWAKE ( init tasks )
  0 !IO ( init i/o device )
  HEX  -1 SET-ORDER DEFINITIONS
  CR [ =VERSION ] LITERAL COUNT TYPE
  CR [ =(C) ] LITERAL COUNT TYPE
  CR QUIT ;

CREATE 0/? ( divide by zero flag )
  D# 1 CELLS ALLOT ( error count )
  D# 1 CELLS ALLOT ( int0 offset )
  D# 1 CELLS ALLOT ( int0 segment )

PROC INT00 ( divide by zero trap )
  0/? inc
  D# -1 ## ax mov  cwd  ax bx mov \ ???
  iret
END-CODE

CODE BYE ( -- ) ( 15.6.2.0830 )
\ =====================
  0/? CELL+ dx lds
  H# 02500 ## ax mov ( restore divide by zero )
  H# 021 int
\ =====================
  H# 20 int          ( terminate process )
END-CODE

PROC VCOLD             ( cold start entry )
  cli                  ( disable interrupt for old 808x CPU bug )
  cs ax mov  ax ds mov ( DS=CS )
  ax ss mov            ( SS=CS )
  SUP ## bp mov        ( system user pointer )
  D# 1 CELLS bp [] sp mov ( init SP )
  D# 0 CELLS bp [] bp mov ( init RP )
  sti                  ( enable interrrupts )
\ =====================
  RESET ## dx mov      ( ^C on output MS-DOS only )
  H# 2523 ## ax mov    ( set ^C interrupt Int23 )
  H# 21 int
\ =====================
  H# 03500 ## ax mov   ( get vector int00 )
  H# 021 int
  bx 0/? CELL+ mov     ( save old offset )
  es 0/? D# 2 CELLS + mov ( save old segment )
  INT00 ## dx mov
  H# 02500 ## ax mov   ( install divide by zero handler )
  H# 021 int
\ =====================
  cld                  ( direction flag, increment )
  ' COLD ## di mov     ( first word to execute ) \ ITC
  D# 0 di [] jmp          ( start eForth )
END-CODE

CR .( Metacompile End ) ]META