WIP to find crashing problem generating eturtle.exe
[hf86v099.git] / boot.f
1 \ Nick\r
2 10 CONSTANT linefeed-char\r
3 13 CONSTANT carriage-return-char\r
4 32 CONSTANT blank-char-value\r
5 \r
6 1 CONSTANT char-size\r
7 2 CONSTANT cell-size\r
8 cell-size 8 * CONSTANT cell-size-in-bits\r
9 \r
10 16 BASE !\r
11   0FF CONSTANT max-char\r
12   7FFF CONSTANT max-signed\r
13   0FFFF CONSTANT max-unsigned\r
14   8000 CONSTANT max-negative\r
15 \r
16   20 CONSTANT =compo\r
17   40 CONSTANT =immed\r
18   80 CONSTANT =seman\r
19   1F CONSTANT =mask\r
20 DECIMAL\r
21 \r
22 258 CONSTANT size-of-PAD\r
23 \r
24 8 CONSTANT bsp#\r
25 9 CONSTANT tab#\r
26 13 CONSTANT cr#\r
27 10 CONSTANT lf#\r
28 127 CONSTANT del#\r
29 \r
30 16 BASE !\r
31   0E890 CONSTANT call-code\r
32 DECIMAL\r
33 \r
34 \ ;;;;;;;;;;;;;;;\r
35 \ System dependent words -- Must be re-definded for each system.\r
36 \ ;;;;;;;;;;;;;;;\r
37 \ I/O words must be redefined if serial communication is used instead of\r
38 \ keyboard. Following words are for MS-DOS system.\r
39 \r
40 \   TX?         ( -- flag )\r
41 \               Return true if output device is ready or device state is\r
42 \               indeterminate.\r
43 \r
44 \               $CONST  NameTXQ,TXQ,TRUEE       ;always true for MS-DOS\r
45 \r
46 \   CR          ( -- )                          \ CORE\r
47 \               Carriage return and linefeed.\r
48 \r
49 : CR            carriage-return-char EMIT  linefeed-char EMIT ;\r
50 \r
51 \               $COLON  NameCR,CR\r
52 \               DW      DoLIT,CRR,EMIT,DoLIT,LFF,EMIT,EXIT\r
53 \r
54 \   hi          ( -- )\r
55 \r
56 : hi            CR ." hForth "\r
57                 S" CPU" ENVIRONMENT? DROP TYPE SPACE\r
58                 S" model" ENVIRONMENT? DROP TYPE SPACE [CHAR] v EMIT\r
59                 S" version"  ENVIRONMENT? DROP TYPE\r
60                 ."  by Wonyong Koh, 1997" CR\r
61                 ." ALL noncommercial and commercial uses are granted." CR\r
62                 ." Please send comment, bug report and suggestions to:" CR\r
63                 ."   wykoh@pado.krict.re.kr or wykoh@hitel.kol.co.kr" CR ;\r
64 \r
65 \               $COLON  NameHI,HI\r
66 \               DW      CR,DoLIT,HiStr1,COUNT,TYPEE\r
67 \               DW      DoLIT,CPUQStr,COUNT,ENVIRONMENTQuery,DROP,TYPEE,SPACE\r
68 \               DW      DoLIT,ModelQStr,COUNT,ENVIRONMENTQuery,DROP,TYPEE\r
69 \               DW      SPACE,DoLIT,'v',EMIT\r
70 \               DW      DoLIT,VersionQStr,COUNT,ENVIRONMENTQuery,DROP,TYPEE\r
71 \               DW      DoLIT,HiStr2,COUNT,TYPEE,CR\r
72 \               DW      DoLIT,HiStr3,COUNT,TYPEE,CR\r
73 \               DW      DoLIT,HiStr4,COUNT,TYPEE,CR\r
74 \               DW      DoLIT,HiStr5,COUNT,TYPEE,CR,EXIT\r
75 \r
76 \   COLD        ( -- )\r
77 \               The cold start sequence execution word.\r
78 \r
79 : COLD          sp0 sp! rp0 rp!                 \ initialize stack\r
80                 'init-i/o EXECUTE\r
81                 'boot EXECUTE\r
82                 QUIT ;                          \ start interpretation\r
83 \r
84 \               $COLON  NameCOLD,COLD\r
85 \               DW      SPZero,SPStore,RPZero,RPStore\r
86 \               DW      TickINIT_IO,EXECUTE,TickBoot,EXECUTE\r
87 \               DW      QUIT\r
88 \r
89 \   set-i/o ( -- )\r
90 \               Set input/output device.\r
91 \r
92 : set-i/o       S" CON" stdin ;                 \ MS-DOS only\r
93 \r
94 \               $COLON  NameSet_IO,Set_IO\r
95 \ Nick removed this, want to use ordinary DOS redirection instead\r
96 \               DW      DoLIT,Set_IOstr         ;MS-DOS only\r
97 \               DW      COUNT,STDIN             ;MS-DOS only\r
98 \               DW      EXIT\r
99 \r
100 \   asciiz      ( ca1 u -- ca2 )\r
101 \               Return ASCIIZ string.\r
102 \r
103 : asciiz        HERE SWAP 2DUP + 0 SWAP C! CHARS MOVE HERE ;\r
104 \r
105 \               $COLON  NameASCIIZ,ASCIIZ\r
106 \               DW      HERE,SWAP,TwoDUP,Plus,DoLIT,0\r
107 \               DW      SWAP,CStore,CHARS,MOVE,HERE,EXIT\r
108 \r
109 \   stdin       ( ca u -- )\r
110 \r
111 : stdin         asciiz redirect ?DUP\r
112                 IF -38 THROW THEN       \ non-existent file\r
113                 ; COMPILE-ONLY\r
114 \r
115 \               $COLON  NameSTDIN,STDIN\r
116 \               DW      ASCIIZ,Redirect,QuestionDUP,ZBranch,STDIN1\r
117 \               DW      DoLIT,-38,THROW\r
118 \ STDIN1                DW      EXIT\r
119 \r
120 \   <<          ( "<spaces>ccc" -- )\r
121 \               Redirect input from the file 'ccc'. Should be used only in\r
122 \               interpretation state.\r
123 \r
124 : <<            STATE @ IF ." Do not use '<<' in a definition." ABORT THEN\r
125                 PARSE-WORD stdin SOURCE >IN !  DROP ; IMMEDIATE\r
126 \r
127 \               $COLON  NameFROM,FROM\r
128 \               DW      DoLIT,AddrSTATE,Fetch,ZBranch,FROM1\r
129 \               DW      CR\r
130 \               DW      DoLIT,FROMstr\r
131 \               DW      COUNT,TYPEE,ABORT\r
132 \ FROM1         DW      PARSE_WORD,STDIN,SOURCE,DoLIT,AddrToIN,Store,DROP,EXIT\r
133 \r
134 \ ;;;;;;;;;;;;;;;\r
135 \ Non-Standard words - Processor-dependent definitions\r
136 \       16 bit Forth for 8086/8\r
137 \ ;;;;;;;;;;;;;;;\r
138 \r
139 \   PAUSE       ( -- )\r
140 \               Stop current task and transfer control to the task of which\r
141 \               'status' USER variable is stored in 'follower' USER variable\r
142 \               of current task.\r
143 \r
144 \ problem\r
145 \ : PAUSE               rp@ DUP sp@ stackTop !  follower @ code@ >R ; COMPILE-ONLY\r
146 \r
147 \                 $COLON  NamePAUSE,PAUSE\r
148 \                 DW      RPFetch,DUPP,SPFetch,StackTop,Store\r
149 \                 DW      Follower,Fetch,CodeFetch,ToR,EXIT\r
150 \r
151 \               $CODE   NamePAUSE,PAUSE\r
152 \               PUSH    BX\r
153 \               XCHG    BP,SP\r
154 \               PUSH    SI\r
155 \               XCHG    BP,SP\r
156 \               PUSH    BP\r
157 \               MOV     BX,WORD PTR AddrUserP\r
158 \ StackTopOffset = SysStackTop - SysUserP\r
159 \               MOV     [BX+StackTopOffset],SP\r
160 \ FollowerOffset = SysFollower - SysUserP\r
161 \               MOV     BX,[BX+FollowerOffset]\r
162 \               MOV     SI,CS:[BX]\r
163 \               $NEXT\r
164 \r
165 \   wake        ( -- )\r
166 \               Wake current task.\r
167 \r
168 : wake          R> CELL+ code@ userP !  \ userP points 'follower' of current task\r
169                 stackTop @ sp! DROP     \ set data stack\r
170                 rp! ; COMPILE-ONLY      \ set return stack\r
171 \r
172 \                 $COLON  NameWake,Wake\r
173 \                 DW      RFrom,CELLPlus,CodeFetch,DoLIT,AddrUserP,Store\r
174 \                 DW      StackTop,Fetch,SPStore,DROP,RPStore,EXIT\r
175 \r
176 \               $CODE   NameWake,Wake\r
177 \               MOV     BX,CS:[SI+CELLL]\r
178 \               MOV     WORD PTR AddrUserP,BX\r
179 \               MOV     SP,[BX+StackTopOffset]\r
180 \               POP     BP\r
181 \               XCHG    BP,SP\r
182 \               POP     SI\r
183 \               XCHG    BP,SP\r
184 \               POP     BX\r
185 \               $NEXT\r
186 \r
187 \   same?       ( c-addr1 c-addr2 u -- -1|0|1 )\r
188 \               Return 0 if two strings, ca1 u and ca2 u, are same; -1 if\r
189 \               string, ca1 u is smaller than ca2 u; 1 otherwise. Used by\r
190 \               '(search-wordlist)'. Code definition is preferred to speed up\r
191 \               interpretation. Colon definition is shown below.\r
192 \r
193 : same?         ?DUP IF         \ null strings are always same\r
194                    0 DO OVER C@ OVER C@ XOR\r
195                         IF UNLOOP C@ SWAP C@ > 2* 1+ EXIT THEN\r
196                         CHAR+ SWAP CHAR+ SWAP\r
197                    LOOP\r
198                 THEN 2DROP 0 ;\r
199 \r
200 \                 $COLON  NameSameQ,SameQ\r
201 \                 DW      QuestionDUP,ZBranch,SAMEQ4\r
202 \                 DW      DoLIT,0,DoDO\r
203 \ SAMEQ3          DW      OVER,CFetch,OVER,CFetch,XORR,ZBranch,SAMEQ2\r
204 \                 DW      UNLOOP,CFetch,SWAP,CFetch,GreaterThan\r
205 \                 DW      TwoStar,OnePlus,EXIT\r
206 \ SAMEQ2          DW      CHARPlus,SWAP,CHARPlus\r
207 \                 DW      DoLOOP,SAMEQ3\r
208 \ SAMEQ4          DW      TwoDROP,DoLIT,0,EXIT\r
209 \r
210 \               $CODE   NameSameQ,SameQ\r
211 \               MOV     CX,BX\r
212 \               MOV     AX,DS\r
213 \               MOV     ES,AX\r
214 \               MOV     DX,SI           ;save SI\r
215 \               MOV     BX,-1\r
216 \               POP     DI\r
217 \               POP     SI\r
218 \               OR      CX,CX\r
219 \               JZ      SAMEQ5\r
220 \               REPE CMPSB\r
221 \               JL      SAMEQ1\r
222 \               JZ      SAMEQ5\r
223 \               INC     BX\r
224 \ SAMEQ5:       INC     BX\r
225 \ SAMEQ1:       MOV     SI,DX\r
226 \               $NEXT\r
227 \r
228 \   (search-wordlist)   ( c-addr u wid -- 0 | xt f 1 | xt f -1)\r
229 \               Search word list for a match with the given name.\r
230 \               Return execution token and not-compile-only flag and\r
231 \               -1 or 1 ( IMMEDIATE) if found. Return 0 if not found.\r
232 \\r
233 \               format is: wid---->[   a    ]\r
234 \                                      |\r
235 \                                      V\r
236 \               [   xt'  ][   a'   ][ccbbaann][ggffeedd]...\r
237 \                             |\r
238 \                             +--------+\r
239 \                                      V\r
240 \               [   xt'' ][   a''  ][ccbbaann][ggffeedd]...\r
241 \\r
242 \               a, a' etc. point to the cell that contains the name of the\r
243 \               word. The length is in the low byte of the cell (little byte\r
244 \               for little-endian, big byte for big-endian).\r
245 \               Eventually, a''' contains 0 to indicate the end of the wordlist\r
246 \               (oldest entry). a=0 indicates an empty wordlist.\r
247 \               xt is the xt of the word. aabbccddeedd etc. is the name of\r
248 \               the word, packed into cells.\r
249 \r
250 : (search-wordlist)\r
251                 ROT >R SWAP DUP 0= IF -16 THROW THEN\r
252                                 \ attempt to use zero-length string as a name\r
253                 >R              \ wid  R: ca1 u\r
254                 BEGIN @         \ ca2  R: ca1 u\r
255                    DUP 0= IF R> R> 2DROP EXIT THEN      \ not found\r
256                    DUP COUNT [ =mask ] LITERAL AND R@ = \ ca2 ca2+char f\r
257                       IF   R> R@ SWAP DUP >R            \ ca2 ca2+char ca1 u\r
258                            same?                        \ ca2 flag\r
259                     \ ELSE DROP -1      \ unnecessary since ca2+char is not 0.\r
260                       THEN\r
261                 WHILE cell-             \ pointer to next word in wordlist\r
262                 REPEAT\r
263                 R> R> 2DROP DUP name>xt SWAP            \ xt ca2\r
264                 C@ 2DUP [ =seman ] LITERAL AND 0= 0=    \ xt char xt f\r
265                 AND TO specialComp?\r
266                 DUP [ =compo ] LITERAL AND 0= SWAP\r
267                 [ =immed ] LITERAL AND 0= 2* 1+ ;\r
268 \r
269 \                 $COLON  NameParenSearch_Wordlist,ParenSearch_Wordlist\r
270 \                 DW      ROT,ToR,SWAP,DUPP,ZBranch,PSRCH6\r
271 \                 DW      ToR\r
272 \ PSRCH1          DW      Fetch\r
273 \                 DW      DUPP,ZBranch,PSRCH9\r
274 \                 DW      DUPP,COUNT,DoLIT,MASKK,ANDD,RFetch,Equals\r
275 \                 DW      ZBranch,PSRCH5\r
276 \                 DW      RFrom,RFetch,SWAP,DUPP,ToR,SameQ\r
277 \ PSRCH5          DW      ZBranch,PSRCH3\r
278 \                 DW      CellMinus,Branch,PSRCH1\r
279 \ PSRCH3          DW      RFrom,RFrom,TwoDROP,DUPP,NameToXT,SWAP\r
280 \                 DW      CFetch,TwoDUP,DoLIT,SEMAN,ANDD,ZeroEquals,ZeroEquals\r
281 \                 DW      ANDD,DoTO,AddrSpecialCompQ\r
282 \                 DW      DUPP,DoLIT,COMPO,ANDD,ZeroEquals,SWAP\r
283 \                 DW      DoLIT,IMMED,ANDD,ZeroEquals,TwoStar,OnePlus,EXIT\r
284 \ PSRCH9          DW      RFrom,RFrom,TwoDROP,EXIT\r
285 \ PSRCH6          DW      DoLIT,-16,THROW\r
286 \r
287 \               $CODE   NameParenSearch_Wordlist,ParenSearch_Wordlist\r
288 \               POP     AX      ;u\r
289 \               POP     DX      ;c-addr\r
290 \               OR      AX,AX\r
291 \               JZ      PSRCH1\r
292 \               PUSH    SI\r
293 \               MOV     CX,DS\r
294 \               MOV     ES,CX\r
295 \               SUB     CX,CX\r
296 \ PSRCH2:       MOV     BX,[BX]\r
297 \               OR      BX,BX\r
298 \               JZ      PSRCH4          ; end of wordlist?\r
299 \               MOV     CL,[BX]\r
300 \               SUB     BX,CELLL        ;pointer to nextword\r
301 \               AND     CL,MASKK        ;max name length = MASKK\r
302 \               CMP     CL,AL\r
303 \               JNZ     PSRCH2\r
304 \               MOV     SI,DX\r
305 \               MOV     DI,BX\r
306 \               ADD     DI,CELLL+CHARR\r
307 \               REPE CMPSB\r
308 \               JNZ     PSRCH2\r
309 \               POP     SI\r
310 \               PUSH    [BX-CELLL]      ;xt\r
311 \               MOV     AL,0FFh\r
312 \               MOV     CL,[BX+CELLL]\r
313 \               AND     AL,CL           ;test SEMAN = 080h\r
314 \               CBW\r
315 \               CWD\r
316 \               AND     DX,[BX-CELLL]\r
317 \               MOV     AddrSpecialCompQ,DX\r
318 \               XOR     DX,DX\r
319 \               TEST    CL,COMPO\r
320 \               JNZ     PSRCH5\r
321 \               DEC     DX\r
322 \ PSRCH5:       PUSH    DX\r
323 \               TEST    CL,IMMED\r
324 \               MOV     BX,-1\r
325 \               JZ      PSRCH3\r
326 \               NEG     BX\r
327 \ PSRCH3:       $NEXT\r
328 \ PSRCH1:       MOV     BX,-16  ;attempt to use zero-length string as a name\r
329 \               JMP     THROW\r
330 \ PSRCH4:       POP     SI\r
331 \               $NEXT\r
332 \r
333 \   ?call       ( xt1 -- xt1 0 | code-addr xt2 )\r
334 \               Return xt of the CALLed run-time word if xt starts with machine\r
335 \               CALL instruction and leaves the next cell address after the\r
336 \               CALL instruction. Otherwise leaves the original xt1 and zero.\r
337 \r
338 : ?call         DUP code@ call-code =\r
339                 IF   CELL+ DUP code@ SWAP CELL+ DUP ROT + EXIT THEN\r
340                         \ Direct Threaded Code 8086 relative call\r
341                 0 ;\r
342 \r
343 \                 $COLON  NameQCall,QCall\r
344 \                 DW      DUPP,CodeFetch,DoLIT,CALLL,Equals,ZBranch,QCALL1\r
345 \                 DW      CELLPlus,DUPP,CodeFetch,SWAP,CELLPlus,DUPP,ROT,Plus\r
346 \                 DW      EXIT\r
347 \ QCALL1          DW      DoLIT,0,EXIT\r
348 \r
349 \               $CODE   NameQCall,QCall\r
350 \               MOV     AX,CS:[BX]\r
351 \               CMP     AX,CALLL\r
352 \               JE      QCALL1\r
353 \               PUSH    BX\r
354 \               XOR     BX,BX\r
355 \               $NEXT\r
356 \ QCALL1:       ADD     BX,2*CELLL\r
357 \               PUSH    BX\r
358 \               ADD     BX,CS:[BX-CELLL]\r
359 \               $NEXT\r
360 \r
361 \   xt,         ( xt1 -- xt2 )\r
362 \               Take a run-time word xt1 for :NONAME , CONSTANT , VARIABLE and\r
363 \               CREATE . Return xt2 of current definition.\r
364 \r
365 : xt,           xhere ALIGNED DUP TO xhere SWAP\r
366                 call-code code,         \ Direct Threaded Code\r
367                 xhere CELL+ - code, ;   \ 8086 relative call\r
368 \r
369 \                 $COLON  NamextComma,xtComma\r
370 \                 DW      XHere,ALIGNED,DUPP,DoTO,AddrXHere,SWAP\r
371 \                 DW      DoLIT,CALLL,CodeComma\r
372 \                 DW      XHere,CELLPlus,Minus,CodeComma,EXIT\r
373 \r
374 \               $CODE   NamextComma,xtComma\r
375 \               MOV     AX,AddrXHere\r
376 \               XCHG    BX,AX\r
377 \               INC     BX\r
378 \               AND     BX,0FFFEh\r
379 \               MOV     WORD PTR CS:[BX],CALLL\r
380 \               MOV     CX,BX\r
381 \               ADD     CX,2*CELLL\r
382 \               MOV     AddrXHere,CX\r
383 \               SUB     AX,CX\r
384 \               MOV     CS:[BX+CELLL],AX\r
385 \               $NEXT\r
386 \r
387 \   doLIT       ( -- x )\r
388 \               Push an inline literal. The inline literal is at the current\r
389 \               value of the fpc, so put it onto the stack and point past it.\r
390 \r
391 \               $CODE   NameDoLIT,DoLIT\r
392 \               PUSH    BX\r
393 \               LODS    WORD PTR CS:[SI]\r
394 \               MOV     BX,AX\r
395 \               $NEXT\r
396 \r
397 \   doCONST     ( -- x )\r
398 \               Run-time routine of CONSTANT and initializable system\r
399 \               VARIABLE. When you quote a constant or variable you execute\r
400 \               its code, which consists of a call to here, followed by an\r
401 \               inline literal. The literal is a constant (for a CONSTANT) or\r
402 \               the address at which a VARIABLE's value is stored. Although\r
403 \               you come here as the result of a native machine call, you\r
404 \               never go back to the return address -- you jump back up a\r
405 \               level by continuing at the new fpc value. For 8086, Z80 the\r
406 \               inline literal is at the return address stored on the top of\r
407 \               the hardware stack.\r
408 \r
409 \               $CODE   NameDoCONST,DoCONST\r
410 \               MOV     DI,SP\r
411 \               XCHG    BX,[DI]\r
412 \               MOV     BX,CS:[BX]\r
413 \               $NEXT\r
414 \r
415 \   doVALUE     ( -- x )\r
416 \               Run-time routine of VALUE. Return the value of VALUE word.\r
417 \               This is like an invocation of doCONST for a VARIABLE but\r
418 \               instead of returning the address of the variable, we return\r
419 \               the value of the variable -- in other words, there is another\r
420 \               level of indirection.\r
421 \r
422 \               $CODE   NameDoVALUE,DoVALUE\r
423 \               MOV     DI,SP\r
424 \               XCHG    BX,[DI]\r
425 \               MOV     BX,CS:[BX]\r
426 \               MOV     BX,[BX]\r
427 \               $NEXT\r
428 \r
429 \   doCREATE    ( -- a-addr )\r
430 \               Run-time routine of CREATE. For CREATEd words with an\r
431 \               associated DOES>, get the address of the CREATEd word's data\r
432 \               space and execute the DOES> actions. For CREATEd word without\r
433 \               an associated DOES>, return the address of the CREATE'd word's\r
434 \               data space. A CREATEd word starts its execution through this\r
435 \               routine in exactly the same way as a colon definition uses\r
436 \               doLIST. In other words, we come here through a native machine\r
437 \               branch.\r
438 \\r
439 \               Structure of CREATEd word:\r
440 \                       | call-doCREATE | 0 or DOES> code addr | a-addr |\r
441 \\r
442 \               The DOES> address holds a native call to doLIST. This routine\r
443 \               doesn't alter the fpc. We never come back *here* so we never\r
444 \               need to preserve an address that would bring us back *here*.\r
445 \\r
446 \               Example : myVARIABLE CREATE , DOES> ;\r
447 \               56 myVARIABLE JIM\r
448 \               JIM \ stacks the address of the data cell that contains 56\r
449 \r
450 : doCREATE                SWAP            \ switch BX and top of 8086 stack item\r
451                   DUP CELL+ code@ SWAP code@ ?DUP IF EXECUTE THEN\r
452                   ; COMPILE-ONLY\r
453 \r
454 \                 $COLON  NameDoCREATE,DoCREATE\r
455 \                 DW      SWAP,CELLPlus,DUPP,CodeFetch,SWAP,CodeFetch\r
456 \                 DW      QuestionDUP,ZBranch,DOCREAT1\r
457 \                 DW      EXECUTE\r
458 \ DOCREAT1        DW      EXIT\r
459 \r
460 \               $CODE   NameDoCREATE,DoCREATE\r
461 \               MOV     DI,SP\r
462 \               XCHG    BX,[DI]\r
463 \               MOV     AX,CS:[BX]\r
464 \               MOV     BX,CS:[BX+CELLL]\r
465 \               OR      AX,AX\r
466 \               JNZ     DOCREAT1\r
467 \               $NEXT\r
468 \ DOCREAT1:     JMP     AX\r
469 \               $ALIGN\r
470 \r
471 \   doTO        ( x -- )\r
472 \               Run-time routine of TO. Store x at the address in the\r
473 \               following cell. The inline literal holds the address\r
474 \               to be modified.\r
475 \r
476 \               $CODE   NameDoTO,DoTO\r
477 \               LODS    WORD PTR CS:[SI]\r
478 \               XCHG    BX,AX\r
479 \               MOV     [BX],AX\r
480 \               POP     BX\r
481 \               $NEXT\r
482 \r
483 \   doUSER      ( -- a-addr )\r
484 \               Run-time routine of USER. Return address of data space.\r
485 \               This is like doCONST but a variable offset is added to the\r
486 \               result. By changing the value at AddrUserP (which happens\r
487 \               on a taskswap) the whole set of user variables is switched\r
488 \               to the set for the new task.\r
489 \r
490 \               $CODE   NameDoUSER,DoUSER\r
491 \               MOV     DI,SP\r
492 \               XCHG    BX,[DI]\r
493 \               MOV     BX,CS:[BX]\r
494 \               ADD     BX,AddrUserP\r
495 \               $NEXT\r
496 \r
497 \   doLIST      ( -- ) ( R: -- nest-sys )\r
498 \               Process colon list.\r
499 \               The first word of a definition (the xt for the word) is a\r
500 \               native machine-code instruction for the target machine. For\r
501 \               high-level definitions, that code is emitted by xt, and\r
502 \               performs a call to doLIST. doLIST executes the list of xt that\r
503 \               make up the definition. The final xt in the definition is EXIT.\r
504 \               The address of the first xt to be executed is passed to doLIST\r
505 \               in a target-specific way. Two examples:\r
506 \               Z80, 8086: native machine call, leaves the return address on\r
507 \               the hardware stack pointer, which is used for the data stack.\r
508 \r
509 \               $CODE   NameDoLIST,DoLIST\r
510 \               SUB     BP,2\r
511 \               MOV     [BP],SI                 ;push return stack\r
512 \               POP     SI                      ;new list address\r
513 \               $NEXT\r
514 \r
515 \   doLOOP      ( -- ) ( R: loop-sys1 -- | loop-sys2 )\r
516 \               Run time routine for LOOP.\r
517 \r
518 \               $CODE   NameDoLOOP,DoLOOP\r
519 \               INC     WORD PTR [BP]           ;increase loop count\r
520 \               JO      DoLOOP1                 ;?loop end\r
521 \               MOV     SI,CS:[SI]              ;no, go back\r
522 \               $NEXT\r
523 \ DoLOOP1:      ADD     SI,CELLL                ;yes, continue past the branch offset\r
524 \               ADD     BP,2*CELLL              ;clear return stack\r
525 \               $NEXT\r
526 \r
527 \   do+LOOP     ( n -- ) ( R: loop-sys1 -- | loop-sys2 )\r
528 \               Run time routine for +LOOP.\r
529 \r
530 \               $CODE   NameDoPLOOP,DoPLOOP\r
531 \               ADD     WORD PTR [BP],BX        ;increase loop count\r
532 \               JO      DoPLOOP1                ;?loop end\r
533 \               MOV     SI,CS:[SI]              ;no, go back\r
534 \               POP     BX\r
535 \               $NEXT\r
536 \ DoPLOOP1:     ADD     SI,CELLL                ;yes, continue past the branch offset\r
537 \               ADD     BP,2*CELLL              ;clear return stack\r
538 \               POP     BX\r
539 \               $NEXT\r
540 \r
541 \   0branch     ( flag -- )\r
542 \               Branch if flag is zero.\r
543 \r
544 \               $CODE   NameZBranch,ZBranch\r
545 \               OR      BX,BX                   ;?flag=0\r
546 \               JZ      ZBRAN1                  ;yes, so branch\r
547 \               ADD     SI,CELLL                ;point IP to next cell\r
548 \               POP     BX\r
549 \               $NEXT\r
550 \ ZBRAN1:       MOV     SI,CS:[SI]              ;IP:=(IP)\r
551 \               POP     BX\r
552 \               $NEXT\r
553 \r
554 \   branch      ( -- )\r
555 \               Branch to an inline address.\r
556 \r
557 \               $CODE   NameBranch,Branch\r
558 \               MOV     SI,CS:[SI]              ;IP:=(IP)\r
559 \               $NEXT\r
560 \r
561 \   rp@         ( -- a-addr )\r
562 \               Push the current RP to the data stack.\r
563 \r
564 \               $CODE   NameRPFetch,RPFetch\r
565 \               PUSH    BX\r
566 \               MOV     BX,BP\r
567 \               $NEXT\r
568 \r
569 \   rp!         ( a-addr -- )\r
570 \               Set the return stack pointer.\r
571 \r
572 \               $CODE   NameRPStore,RPStore\r
573 \               MOV     BP,BX\r
574 \               POP     BX\r
575 \               $NEXT\r
576 \r
577 \   sp@         ( -- a-addr )\r
578 \               Push the current data stack pointer.\r
579 \r
580 \               $CODE   NameSPFetch,SPFetch\r
581 \               PUSH    BX\r
582 \               MOV     BX,SP\r
583 \               $NEXT\r
584 \r
585 \   sp!         ( a-addr -- )\r
586 \               Set the data stack pointer.\r
587 \r
588 \               $CODE   NameSPStore,SPStore\r
589 \               MOV     SP,BX\r
590 \               POP     BX\r
591 \               $NEXT\r
592 \r
593 \   um+         ( u1 u2 -- u3 1|0 )\r
594 \               Add two unsigned numbers, return the sum and carry.\r
595 \r
596 \               $CODE   NameUMPlus,UMPlus\r
597 \               XOR     CX,CX\r
598 \               POP     AX\r
599 \               ADD     BX,AX\r
600 \               PUSH    BX                      ;push sum\r
601 \               RCL     CX,1                    ;get carry\r
602 \               MOV     BX,CX\r
603 \               $NEXT\r
604 \r
605 \   code!       ( x code-addr -- )\r
606 \               Store x at a code space address.\r
607 \r
608 \               $CODE   NameCodeStore,CodeStore\r
609 \               POP     CS:[BX]\r
610 \               POP     BX\r
611 \               $NEXT\r
612 \r
613 \   codeB!      ( b code-addr -- )\r
614 \               Store byte at a code space address.\r
615 \r
616 \               $CODE   NameCodeBStore,CodeBStore\r
617 \               POP     AX\r
618 \               MOV     CS:[BX],AL\r
619 \               POP     BX\r
620 \               $NEXT\r
621 \r
622 \   code@       ( code-addr -- x )\r
623 \               Push the contents at code space addr to the data stack.\r
624 \r
625 \               $CODE   NameCodeFetch,CodeFetch\r
626 \               MOV     BX,CS:[BX]\r
627 \               $NEXT\r
628 \r
629 \   codeB@      ( code-addr -- b )\r
630 \               Push the contents at code space byte addr to the data stack.\r
631 \r
632 \               $CODE   NameCodeBFetch,CodeBFetch\r
633 \               MOV     BL,CS:[BX]\r
634 \               XOR     BH,BH\r
635 \               $NEXT\r
636 \r
637 \   code,       ( x -- )\r
638 \               Reserve one cell in code space and store x in it.\r
639 \r
640 : code,         xhere DUP CELL+ TO xhere code! ;\r
641 \r
642 \                 $COLON  NameCodeComma,CodeComma\r
643 \                 DW      XHere,DUPP,CELLPlus,DoTO,AddrXHere,CodeStore,EXIT\r
644 \r
645 \               $CODE   NameCodeComma,CodeComma\r
646 \               MOV     DI,AddrXHere\r
647 \               MOV     CS:[DI],BX\r
648 \               ADD     DI,CELLL\r
649 \               POP     BX\r
650 \               MOV     AddrXHere,DI\r
651 \               $NEXT\r
652 \r
653 \ ;;;;;;;;;;;;;;;\r
654 \ Standard words - Processor-dependent definitions\r
655 \       16 bit Forth for 8086/8\r
656 \ ;;;;;;;;;;;;;;;\r
657 \r
658 \   ALIGN       ( -- )                          \ CORE\r
659 \               Align the data space pointer.\r
660 \r
661 : ALIGN         HERE ALIGNED TO HERE ;\r
662 \r
663 \               $COLON  NameALIGNN,ALIGNN\r
664 \               DW      HERE,ALIGNED,DoTO,AddrHERE,EXIT\r
665 \r
666 \   ALIGNED     ( addr -- a-addr )              \ CORE\r
667 \               Align address to the cell boundary.\r
668 \r
669 : ALIGNED       DUP 0 cell-size UM/MOD DROP DUP\r
670                 IF cell-size SWAP - THEN + ;\r
671 \r
672 \                 $COLON  NameALIGNED,ALIGNED\r
673 \                 DW      DUPP,DoLIT,0,DoLIT,CELLL\r
674 \                 DW      UMSlashMOD,DROP,DUPP\r
675 \                 DW      ZBranch,ALGN1\r
676 \                 DW      DoLIT,CELLL,SWAP,Minus\r
677 \ ALGN1           DW      Plus,EXIT\r
678 \r
679 \               $CODE   NameALIGNED,ALIGNED\r
680 \               INC     BX\r
681 \               AND     BX,0FFFEh\r
682 \               $NEXT\r
683 \r
684 \   CELLS       ( n1 -- n2 )                    \ CORE\r
685 \               Calculate number of address units for n1 cells.\r
686 \r
687 \ : CELLS               cell-size * ;   \ slow, very portable\r
688 : CELLS         2* ;            \ fast, must be redefined for each system\r
689 \r
690 \                 $COLON  NameCELLS,CELLS\r
691 \                 DW      TwoStar,EXIT\r
692 \r
693 \               $CODE   NameCELLS,CELLS\r
694 \               SHL     BX,1\r
695 \               $NEXT\r
696 \r
697 \   CHARS       ( n1 -- n2 )                    \ CORE\r
698 \               Calculate number of address units for n1 characters.\r
699 \r
700 \ : CHARS               char-size * ;   \ slow, very portable\r
701 : CHARS         ;               \ fast, must be redefined for each system\r
702 \r
703 \              $COLON  NameCHARS,CHARS\r
704 \              DW      EXIT\r
705 \r
706 \   1chars/     ( n1 -- n2 )\r
707 \               Calculate number of chars for n1 address units.\r
708 \r
709 \ : 1chars/             1 CHARS / ;     \ slow, very portable\r
710 : 1chars/               ;               \ fast, must be redefined for each system\r
711 \r
712 \               $COLON  NameOneCharsSlash,OneCharsSlash\r
713 \               DW      EXIT\r
714 \r
715 \   !           ( x a-addr -- )                 \ CORE\r
716 \               Store x at a aligned address.\r
717 \r
718 \               $CODE   NameStore,Store\r
719 \               POP     [BX]\r
720 \               POP     BX\r
721 \               $NEXT\r
722 \r
723 \   0<          ( n -- flag )                   \ CORE\r
724 \               Return true if n is negative.\r
725 \r
726 \               $CODE   NameZeroLess,ZeroLess\r
727 \               MOV     AX,BX\r
728 \               CWD             ;sign extend\r
729 \               MOV     BX,DX\r
730 \               $NEXT\r
731 \r
732 \   0=          ( x -- flag )                   \ CORE\r
733 \               Return true if x is zero.\r
734 \r
735 \               $CODE   NameZeroEquals,ZeroEquals\r
736 \               OR      BX,BX\r
737 \               MOV     BX,TRUEE\r
738 \               JZ      ZEQUAL1\r
739 \               INC     BX\r
740 \ ZEQUAL1:      $NEXT\r
741 \r
742 \   2*          ( x1 -- x2 )                    \ CORE\r
743 \               Bit-shift left, filling the least significant bit with 0.\r
744 \r
745 \               $CODE   NameTwoStar,TwoStar\r
746 \               SHL     BX,1\r
747 \               $NEXT\r
748 \r
749 \   2/          ( x1 -- x2 )                    \ CORE\r
750 \               Bit-shift right, leaving the most significant bit unchanged.\r
751 \r
752 \               $CODE   NameTwoSlash,TwoSlash\r
753 \               SAR     BX,1\r
754 \               $NEXT\r
755 \r
756 \   >R          ( x -- ) ( R: -- x )            \ CORE\r
757 \               Move top of the data stack item to the return stack.\r
758 \r
759 \               $CODE   NameToR,ToR\r
760 \               SUB     BP,CELLL                ;adjust RP\r
761 \               MOV     [BP],BX\r
762 \               POP     BX\r
763 \               $NEXT\r
764 \r
765 \   @           ( a-addr -- x )                 \ CORE\r
766 \               Push the contents at a-addr to the data stack.\r
767 \r
768 \               $CODE   NameFetch,Fetch\r
769 \               MOV     BX,[BX]\r
770 \               $NEXT\r
771 \r
772 \   AND         ( x1 x2 -- x3 )                 \ CORE\r
773 \               Bitwise AND.\r
774 \r
775 \               $CODE   NameANDD,ANDD\r
776 \               POP     AX\r
777 \               AND     BX,AX\r
778 \               $NEXT\r
779 \r
780 \   C!          ( char c-addr -- )              \ CORE\r
781 \               Store char at c-addr.\r
782 \r
783 \               $CODE   NameCStore,CStore\r
784 \               POP     AX\r
785 \               MOV     [BX],AL\r
786 \               POP     BX\r
787 \               $NEXT\r
788 \r
789 \   C@          ( c-addr -- char )              \ CORE\r
790 \               Fetch the character stored at c-addr.\r
791 \r
792 \               $CODE   NameCFetch,CFetch\r
793 \               MOV     BL,[BX]\r
794 \               XOR     BH,BH\r
795 \               $NEXT\r
796 \r
797 \   DROP        ( x -- )                        \ CORE\r
798 \               Discard top stack item.\r
799 \r
800 \               $CODE   NameDROP,DROP\r
801 \               POP     BX\r
802 \               $NEXT\r
803 \r
804 \   DUP         ( x -- x x )                    \ CORE\r
805 \               Duplicate the top stack item.\r
806 \r
807 \               $CODE   NameDUPP,DUPP\r
808 \               PUSH    BX\r
809 \               $NEXT\r
810 \r
811 \   EXECUTE     ( i*x xt -- j*x )               \ CORE\r
812 \               Perform the semantics indentified by execution token, xt.\r
813 \r
814 \               $CODE   NameEXECUTE,EXECUTE\r
815 \               MOV     AX,BX\r
816 \               POP     BX\r
817 \               JMP     AX                      ;jump to the code address\r
818 \               $ALIGN\r
819 \r
820 \   EXIT        ( -- ) ( R: nest-sys -- )       \ CORE\r
821 \               Return control to the calling definition.\r
822 \r
823 \               $CODE   NameEXIT,EXIT\r
824 \               XCHG    BP,SP                   ;exchange pointers\r
825 \               POP     SI                      ;pop return stack\r
826 \               XCHG    BP,SP                   ;restore the pointers\r
827 \               $NEXT\r
828 \r
829 \   MOVE        ( addr1 addr2 u -- )            \ CORE\r
830 \               Copy u address units from addr1 to addr2 if u is greater\r
831 \               than zero. This word is CODE defined since no other Standard\r
832 \               words can handle address unit directly.\r
833 \r
834 \               $CODE   NameMOVE,MOVE\r
835 \               POP     DI\r
836 \               POP     DX\r
837 \               OR      BX,BX\r
838 \               JZ      MOVE2\r
839 \               MOV     CX,BX\r
840 \               XCHG    DX,SI                   ;save SI\r
841 \               MOV     AX,DS\r
842 \               MOV     ES,AX                   ;set ES same as DS\r
843 \               CMP     SI,DI\r
844 \               JC      MOVE1\r
845 \               REP MOVSB\r
846 \               MOV     SI,DX\r
847 \ MOVE2:                POP     BX\r
848 \               $NEXT\r
849 \ MOVE1:                STD\r
850 \               ADD     DI,CX\r
851 \               DEC     DI\r
852 \               ADD     SI,CX\r
853 \               DEC     SI\r
854 \               REP MOVSB\r
855 \               CLD\r
856 \               MOV     SI,DX\r
857 \               POP     BX\r
858 \               $NEXT\r
859 \r
860 \   OR          ( x1 x2 -- x3 )                 \ CORE\r
861 \               Return bitwise inclusive-or of x1 with x2.\r
862 \r
863 \               $CODE   NameORR,ORR\r
864 \               POP     AX\r
865 \               OR      BX,AX\r
866 \               $NEXT\r
867 \r
868 \   OVER        ( x1 x2 -- x1 x2 x1 )           \ CORE\r
869 \               Copy second stack item to top of the stack.\r
870 \r
871 \               $CODE   NameOVER,OVER\r
872 \               MOV     DI,SP\r
873 \               PUSH    BX\r
874 \               MOV     BX,[DI]\r
875 \               $NEXT\r
876 \r
877 \   R>          ( -- x ) ( R: x -- )            \ CORE\r
878 \               Move x from the return stack to the data stack.\r
879 \r
880 \               $CODE   NameRFrom,RFrom\r
881 \               PUSH    BX\r
882 \               MOV     BX,[BP]\r
883 \               ADD     BP,CELLL                ;adjust RP\r
884 \               $NEXT\r
885 \r
886 \   R@          ( -- x ) ( R: x -- x )          \ CORE\r
887 \               Copy top of return stack to the data stack.\r
888 \r
889 \               $CODE   NameRFetch,RFetch\r
890 \               PUSH    BX\r
891 \               MOV     BX,[BP]\r
892 \               $NEXT\r
893 \r
894 \   SWAP        ( x1 x2 -- x2 x1 )              \ CORE\r
895 \               Exchange top two stack items.\r
896 \r
897 \               $CODE   NameSWAP,SWAP\r
898 \               MOV     DI,SP\r
899 \               XCHG    BX,[DI]\r
900 \               $NEXT\r
901 \r
902 \   XOR         ( x1 x2 -- x3 )                 \ CORE\r
903 \               Bitwise exclusive OR.\r
904 \r
905 \               $CODE   NameXORR,XORR\r
906 \               POP     AX\r
907 \               XOR     BX,AX\r
908 \               $NEXT\r
909 \r
910 \ ;;;;;;;;;;;;;;;\r
911 \ System constants and variables\r
912 \ ;;;;;;;;;;;;;;;\r
913 \r
914 \   #order0     ( -- a-addr )\r
915 \               Start address of default search order.\r
916 \r
917 \               $CONST  NameNumberOrder0,NumberOrder0,AddrNumberOrder0\r
918 \r
919 \   'ekey?      ( -- a-addr )\r
920 \               Execution vector of EKEY?.\r
921 \r
922 \               $VALUE  NameTickEKEYQ,TickEKEYQ,AddrTickEKEYQ\r
923 \r
924 \   'ekey       ( -- a-addr )\r
925 \               Execution vector of EKEY.\r
926 \r
927 \               $VALUE  NameTickEKEY,TickEKEY,AddrTickEKEY\r
928 \r
929 \   'emit?      ( -- a-addr )\r
930 \               Execution vector of EMIT?.\r
931 \r
932 \               $VALUE  NameTickEMITQ,TickEMITQ,AddrTickEMITQ\r
933 \r
934 \   'emit       ( -- a-addr )\r
935 \               Execution vector of EMIT.\r
936 \r
937 \               $VALUE  NameTickEMIT,TickEMIT,AddrTickEMIT\r
938 \r
939 \   'init-i/o   ( -- a-addr )\r
940 \               Execution vector to initialize input/output devices.\r
941 \r
942 \               $VALUE  NameTickINIT_IO,TickINIT_IO,AddrTickINIT_IO\r
943 \r
944 \   'prompt     ( -- a-addr )\r
945 \               Execution vector of '.prompt'.\r
946 \r
947 \               $VALUE  NameTickPrompt,TickPrompt,AddrTickPrompt\r
948 \r
949 \   'boot       ( -- a-addr )\r
950 \               Execution vector of COLD.\r
951 \r
952 \               $VALUE  NameTickBoot,TickBoot,AddrTickBoot\r
953 \r
954 \   SOURCE-ID   ( -- 0 | -1 )                   \ CORE EXT\r
955 \               Identify the input source. -1 for string (via EVALUATE) and\r
956 \               0 for user input device.\r
957 \r
958 \               $VALUE  NameSOURCE_ID,SOURCE_ID,AddrSOURCE_ID\r
959 \r
960 \   HERE        ( -- addr )                     \ CORE\r
961 \               Return data space pointer.\r
962 \r
963 \               $VALUE  NameHERE,HERE,AddrHERE\r
964 \r
965 \   xhere       ( -- code-addr )\r
966 \               Return next available code space address.\r
967 \r
968 \               $VALUE  NameXHere,XHere,AddrXHere\r
969 \r
970 \   'doWord     ( -- a-addr )\r
971 \               Execution vectors for 'interpret'.\r
972 \r
973 \               $CONST  NameTickDoWord,TickDoWord,AddrTickDoWord\r
974 \r
975 \   BASE        ( -- a-addr )                   \ CORE\r
976 \               Return the address of the radix base for numeric I/O.\r
977 \r
978 \               $CONST  NameBASE,BASE,AddrBASE\r
979 \r
980 \   THROWMsgTbl ( -- a-addr )                   \ CORE\r
981 \               Return the address of the THROW message table.\r
982 \r
983 \               $CONST  NameTHROWMsgTbl,THROWMsgTbl,AddrTHROWMsgTbl\r
984 \r
985 \   memTop      ( -- a-addr )\r
986 \               Top of free memory.\r
987 \r
988 \               $VALUE  NameMemTop,MemTop,AddrMemTop\r
989 \r
990 \   bal         ( -- n )\r
991 \               Return the depth of control-flow stack.\r
992 \r
993 \               $VALUE  NameBal,Bal,AddrBal\r
994 \r
995 \   notNONAME?  ( -- f )\r
996 \               Used by ';' whether to do 'linkLast' or not\r
997 \r
998 \               $VALUE  NameNotNONAMEQ,NotNONAMEQ,AddrNotNONAMEQ\r
999 \r
1000 \   rakeVar     ( -- a-addr )\r
1001 \               Used by 'rake' to gather LEAVE.\r
1002 \r
1003 \               $CONST  NameRakeVar,RakeVar,AddrRakeVar\r
1004 \r
1005 \   #order      ( -- a-addr )\r
1006 \               Hold the search order stack depth.\r
1007 \r
1008 \               $CONST  NameNumberOrder,NumberOrder,AddrNumberOrder\r
1009 \r
1010 \   current     ( -- a-addr )\r
1011 \               Point to the wordlist to be extended.\r
1012 \r
1013 \               $CONST  NameCurrent,Current,AddrCurrent\r
1014 \r
1015 \   FORTH-WORDLIST   ( -- wid )                 \ SEARCH\r
1016 \               Return wid of Forth wordlist.\r
1017 \r
1018 \               $CONST  NameFORTH_WORDLIST,FORTH_WORDLIST,AddrFORTH_WORDLIST\r
1019 \r
1020 \   NONSTANDARD-WORDLIST   ( -- wid )\r
1021 \               Return wid of non-standard wordlist.\r
1022 \r
1023 \               $CONST  NameNONSTANDARD_WORDLIST,NONSTANDARD_WORDLIST,AddrNONSTANDARD_WORDLIST\r
1024 \r
1025 \   envQList    ( -- wid )\r
1026 \               Return wid of ENVIRONMENT? string list. Never put this wid in\r
1027 \               search-order. It should be used only by SET-CURRENT to add new\r
1028 \               environment query string after addition of a complete wordset.\r
1029 \r
1030 \               $CONST  NameEnvQList,EnvQList,AddrEnvQList\r
1031 \r
1032 \   userP       ( -- a-addr )\r
1033 \               Return address of USER variable area of current task.\r
1034 \r
1035 \               $CONST  NameUserP,UserP,AddrUserP\r
1036 \r
1037 \   SystemTask  ( -- a-addr )\r
1038 \               Return system task's tid.\r
1039 \r
1040 \               $CONST  NameSystemTask,SystemTask,SysTask\r
1041 \r
1042 \   follower    ( -- a-addr )\r
1043 \               Point next task's 'status' USER variable.\r
1044 \r
1045 \               $USER   NameFollower,Follower,SysFollower-SysUserP\r
1046 \r
1047 \   status      ( -- a-addr )\r
1048 \               Status of current task. Point 'pass' or 'wake'.\r
1049 \r
1050 \               $USER   NameStatus,Status,SysStatus-SysUserP\r
1051 \r
1052 \   stackTop    ( -- a-addr )\r
1053 \               Store current task's top of stack position.\r
1054 \r
1055 \               $USER   NameStackTop,StackTop,SysStackTop-SysUserP\r
1056 \r
1057 \   throwFrame  ( -- a-addr )\r
1058 \               THROW frame for CATCH and THROW need to be saved for eack task.\r
1059 \r
1060 \               $USER   NameThrowFrame,ThrowFrame,SysThrowFrame-SysUserP\r
1061 \r
1062 \   taskName    ( -- a-addr )\r
1063 \               Current task's task ID.\r
1064 \r
1065 \               $USER   NameTaskName,TaskName,SysTaskName-SysUserP\r
1066 \r
1067 \   user1       ( -- a-addr )\r
1068 \               One free USER variable for each task.\r
1069 \r
1070 \               $USER   NameUser1,User1,SysUser1-SysUserP\r
1071 \r
1072 \ ENVIRONMENT? strings can be searched using SEARCH-WORDLIST and can be\r
1073 \ EXECUTEd. This wordlist is completely hidden to Forth system except\r
1074 \ ENVIRONMENT? .\r
1075 \r
1076 \ CPU:\r
1077 \               NOP\r
1078 \               CALL    DoLIST\r
1079 \               DW      DoLIT,CPUStr,COUNT,EXIT\r
1080 \r
1081 \ Model:\r
1082 \               NOP\r
1083 \               CALL    DoLIST\r
1084 \               DW      DoLIT,ModelStr,COUNT,EXIT\r
1085 \r
1086 \ Version:\r
1087 \               NOP\r
1088 \               CALL    DoLIST\r
1089 \               DW      DoLIT,VersionStr,COUNT,EXIT\r
1090 \r
1091 \ SlashCOUNTED_STRING:\r
1092 \               NOP\r
1093 \               CALL    DoCONST\r
1094 \               DW      MaxChar\r
1095 \r
1096 \ SlashHOLD:\r
1097 \               NOP\r
1098 \               CALL    DoCONST\r
1099 \               DW      PADSize\r
1100 \r
1101 \ SlashPAD:\r
1102 \               NOP\r
1103 \               CALL    DoCONST\r
1104 \               DW      PADSize\r
1105 \r
1106 \ ADDRESS_UNIT_BITS:\r
1107 \               NOP\r
1108 \               CALL    DoCONST\r
1109 \               DW      8\r
1110 \r
1111 \ CORE:\r
1112 \               NOP\r
1113 \               CALL    DoCONST\r
1114 \               DW      TRUEE\r
1115 \r
1116 \ FLOORED:\r
1117 \               NOP\r
1118 \               CALL    DoCONST\r
1119 \               DW      TRUEE\r
1120 \r
1121 \ MAX_CHAR:\r
1122 \               NOP\r
1123 \               CALL    DoCONST\r
1124 \               DW      MaxChar         ;max value of character set\r
1125 \r
1126 \ MAX_D:\r
1127 \               NOP\r
1128 \               CALL    DoLIST\r
1129 \               DW      DoLIT,MaxUnsigned,DoLIT,MaxSigned,EXIT\r
1130 \r
1131 \ MAX_N:\r
1132 \               NOP\r
1133 \               CALL    DoCONST\r
1134 \               DW      MaxSigned\r
1135 \r
1136 \ MAX_U:\r
1137 \               NOP\r
1138 \               CALL    DoCONST\r
1139 \               DW      MaxUnsigned\r
1140 \r
1141 \ MAX_UD:\r
1142 \               NOP\r
1143 \               CALL    DoLIST\r
1144 \               DW      MAX_U,MAX_U,EXIT\r
1145 \r
1146 \ RETURN_STACK_CELLS:\r
1147 \               NOP\r
1148 \               CALL    DoCONST\r
1149 \               DW      RTCells\r
1150 \r
1151 \ STACK_CELLS:\r
1152 \               NOP\r
1153 \               CALL    DoCONST\r
1154 \               DW      DTCells\r
1155 \r
1156 \ EXCEPTION:\r
1157 \               NOP\r
1158 \               CALL    DoCONST\r
1159 \               DW      TRUEE\r
1160 \r
1161 \ EXCEPTION_EXT:\r
1162 \               NOP\r
1163 \               CALL    DoCONST\r
1164 \               DW      TRUEE\r
1165 \r
1166 \ WORDLISTS:\r
1167 \               NOP\r
1168 \               CALL    DoCONST\r
1169 \               DW      OrderDepth\r
1170 \r
1171 \ ;;;;;;;;;;;;;;;\r
1172 \ Non-Standard words - Colon definitions\r
1173 \ ;;;;;;;;;;;;;;;\r
1174 \r
1175 \   (')         ( "<spaces>name" -- xt 1 | xt -1 )\r
1176 \               Parse a name, find it and return execution token and\r
1177 \               -1 or 1 ( IMMEDIATE) if found\r
1178 \r
1179 : (')           PARSE-WORD search-word ?DUP IF NIP EXIT THEN\r
1180                 errWord 2!      \ if not found error\r
1181                 -13 THROW ;     \ undefined word\r
1182 \r
1183 \               $COLON  NameParenTick,ParenTick\r
1184 \               DW      PARSE_WORD,Search_word,QuestionDUP,ZBranch,PTICK1\r
1185 \               DW      NIP,EXIT\r
1186 \ PTICK1                DW      DoLIT,AddrErrWord,TwoStore,DoLIT,-13,THROW\r
1187 \r
1188 \   (d.)        ( d -- c-addr u )\r
1189 \               Convert a double number to a string.\r
1190 \r
1191 : (d.)          SWAP OVER  DUP 0< IF  DNEGATE  THEN\r
1192                 <#  #S ROT SIGN  #> ;\r
1193 \r
1194 \               $COLON  NameParenDDot,ParenDDot\r
1195 \               DW      SWAP,OVER,DUPP,ZeroLess,ZBranch,PARDD1\r
1196 \               DW      DNEGATE\r
1197 \ PARDD1                DW      LessNumberSign,NumberSignS,ROT\r
1198 \               DW      SIGN,NumberSignGreater,EXIT\r
1199 \r
1200 \   .ok         ( -- )\r
1201 \               Display 'ok'.\r
1202 \r
1203 : .ok           ." okay" ;\r
1204 \r
1205 \               $COLON  NameDotOK,DotOK\r
1206 \               DW      DoLIT,DotOKStr\r
1207 \               DW      COUNT,TYPEE,EXIT\r
1208 \r
1209 \   .prompt         ( -- )\r
1210 \               Disply Forth prompt. This word is vectored.\r
1211 \r
1212 : .prompt               'prompt EXECUTE ;\r
1213 \r
1214 \               $COLON  NameDotOK,DotPrompt\r
1215 \               DW      TickPrompt,EXECUTE,EXIT\r
1216 \r
1217 \   0           ( -- 0 )\r
1218 \               Return zero.\r
1219 \r
1220 \               $CONST  NameZero,Zero,0\r
1221 \r
1222 \   1           ( -- 1 )\r
1223 \               Return one.\r
1224 \r
1225 \               $CONST  NameOne,One,1\r
1226 \r
1227 \   -1          ( -- -1 )\r
1228 \               Return -1.\r
1229 \r
1230 \               $CONST  NameMinusOne,MinusOne,-1\r
1231 \r
1232 \   abort"msg   ( -- a-addr )\r
1233 \               Abort" error message string address.\r
1234 \r
1235 \               $CONST  NameAbortQMsg,AbortQMsg,AddrAbortQMsg\r
1236 \r
1237 \   bal+        ( -- )\r
1238 \               Increase bal by 1.\r
1239 \r
1240 : bal+          bal 1+ TO bal ;\r
1241 \r
1242 \                 $COLON  4,'bal+',BalPlus,_SLINK\r
1243 \                 DW      Bal,OnePlus,DoTO,AddrBal,EXIT\r
1244 \r
1245 \               $CODE   NameBalPlus,BalPlus\r
1246 \               INC     AddrBal\r
1247 \               $NEXT\r
1248 \r
1249 \   bal-        ( -- )\r
1250 \               Decrease bal by 1.\r
1251 \r
1252 : bal-          bal 1- TO bal ;\r
1253 \r
1254 \                 $COLON  NameBalMinus,BalMinus\r
1255 \                 DW      Bal,OneMinus,DoTO,AddrBal,EXIT\r
1256 \r
1257 \               $CODE   NameBalMinus,BalMinus\r
1258 \               DEC     AddrBal\r
1259 \               $NEXT\r
1260 \r
1261 \   cell-       ( a-addr1 -- a-addr2 )\r
1262 \               Return previous aligned cell address.\r
1263 \r
1264 : cell-         [ cell-size NEGATE ] LITERAL + ;\r
1265 \r
1266 \                $COLON  NameCellMinus,CellMinus\r
1267 \                DW      DoLIT,0-CELLL,Plus,EXIT\r
1268 \r
1269 \               $CODE   NameCellMinus,CellMinus\r
1270 \               SUB     BX,CELLL\r
1271 \               $NEXT\r
1272 \r
1273 \   COMPILE-ONLY   ( -- )\r
1274 \               Make the most recent definition an compile-only word.\r
1275 \r
1276 : COMPILE-ONLY  lastName [ =compo ] LITERAL OVER @ OR SWAP ! ;\r
1277 \r
1278 \               $COLON  NameCOMPILE_ONLY,COMPILE_ONLY\r
1279 \               DW      LastName,DoLIT,COMPO,OVER,Fetch,ORR,SWAP,Store,EXIT\r
1280 \r
1281 \   doDO        ( n1|u1 n2|u2 -- ) ( R: -- n1 n2-n1-max_negative )\r
1282 \               Run-time funtion of DO.\r
1283 \r
1284 : doDO          >R max-negative + R> OVER - SWAP R> SWAP >R SWAP >R >R ;\r
1285 \r
1286 \                 $COLON  NameDoDO,DoDO\r
1287 \                 DW      ToR,DoLIT,MaxNegative,Plus,RFrom\r
1288 \                 DW      OVER,Minus,SWAP,RFrom,SWAP,ToR,SWAP,ToR,ToR,EXIT\r
1289 \r
1290 \               $CODE   NameDoDO,DoDO\r
1291 \               SUB     BP,2*CELLL\r
1292 \               POP     AX\r
1293 \               ADD     AX,MaxNegative\r
1294 \               MOV     [BP+CELLL],AX\r
1295 \               SUB     BX,AX\r
1296 \               MOV     [BP],BX\r
1297 \               POP     BX\r
1298 \               $NEXT\r
1299 \r
1300 \   errWord     ( -- a-addr )\r
1301 \               Last found word. To be used to display the word causing error.\r
1302 \r
1303 \               $CONST  NameErrWord,ErrWord,AddrErrWord\r
1304 \r
1305 \   head,       ( xt "<spaces>name" -- )\r
1306 \               Parse a word and build a dictionary entry.\r
1307 \r
1308 : head,         >R  PARSE-WORD DUP 0=\r
1309                 IF errWord 2! -16 THROW THEN\r
1310                                 \ attempt to use zero-length string as a name\r
1311                 DUP =mask > IF -19 THROW THEN   \ definition name too long\r
1312                 2DUP GET-CURRENT SEARCH-WORDLIST  \ name exist?\r
1313                 IF DROP ." redefine " 2DUP TYPE SPACE THEN \ warn if redefined\r
1314                 ALIGN R@ ,                      \ align and store xt\r
1315                 GET-CURRENT @ ,                 \ build wordlist link\r
1316                 HERE DUP >R pack" ALIGNED TO HERE \ pack the name in name space\r
1317                 R> DUP R> cell- code!           \ store name addr in code space\r
1318                 TO lastName ;\r
1319 \r
1320 \               $COLON  NameHeadComma,HeadComma\r
1321 \               DW      ToR,PARSE_WORD,DUPP,ZBranch,HEADC1\r
1322 \               DW      DUPP,DoLIT,MASKK,GreaterThan,ZBranch,HEADC3\r
1323 \               DW      DoLIT,-19,THROW\r
1324 \ HEADC3                DW      TwoDUP,GET_CURRENT,SEARCH_WORDLIST,ZBranch,HEADC2\r
1325 \               DW      DROP\r
1326 \               DW      DoLIT,HEADCstr\r
1327 \               DW      COUNT,TYPEE,TwoDUP,TYPEE,SPACE\r
1328 \ HEADC2                DW      ALIGNN,RFetch,Comma\r
1329 \               DW      GET_CURRENT,Fetch,Comma\r
1330 \               DW      HERE,DUPP,ToR,PackQuote,ALIGNED,DoTO,AddrHERE\r
1331 \               DW      RFrom,DUPP,RFrom,CellMinus,CodeStore\r
1332 \               DW      DoTO,AddrLastName,EXIT\r
1333 \ HEADC1                DW      DoLIT,AddrErrWord,TwoStore,DoLIT,-16,THROW\r
1334 \r
1335 \   hld         ( -- a-addr )\r
1336 \               Hold a pointer in building a numeric output string.\r
1337 \r
1338 \               $CONST  NameHLD,HLD,AddrHLD\r
1339 \r
1340 \   interpret   ( i*x -- j*x )\r
1341 \               Intrepret input string.\r
1342 \r
1343 : interpret     BEGIN  DEPTH 0< IF -4 THROW THEN        \ stack underflow\r
1344                        PARSE-WORD DUP\r
1345                 WHILE  2DUP errWord 2!\r
1346                        search-word          \ ca u 0 | xt f -1 | xt f 1\r
1347                        DUP IF\r
1348                          SWAP STATE @ OR 0= \ compile-only in interpretation\r
1349                          IF -14 THROW THEN  \ interpreting a compile-only word\r
1350                        THEN\r
1351                        1+ 2* STATE @ 1+ + CELLS 'doWord + @ EXECUTE\r
1352                 REPEAT 2DROP ;\r
1353 \r
1354 \               $COLON  NameInterpret,Interpret\r
1355 \ INTERP1       DW      DEPTH,ZeroLess,ZBranch,INTERP2\r
1356 \               DW      DoLIT,-4,THROW\r
1357 \ INTERP2       DW      PARSE_WORD,DUPP,ZBranch,INTERP3\r
1358 \               DW      TwoDUP,DoLIT,AddrErrWord,TwoStore\r
1359 \               DW      Search_word,DUPP,ZBranch,INTERP5\r
1360 \               DW      SWAP,DoLIT,AddrSTATE,Fetch,ORR,ZBranch,INTERP4\r
1361 \ INTERP5       DW      OnePlus,TwoStar,DoLIT,AddrSTATE,Fetch,OnePlus,Plus,CELLS\r
1362 \               DW      DoLIT,AddrTickDoWord,Plus,Fetch,EXECUTE\r
1363 \               DW      Branch,INTERP1\r
1364 \ INTERP3       DW      TwoDROP,EXIT\r
1365 \ INTERP4       DW      DoLIT,-14,THROW\r
1366 \r
1367 \   optiCOMPILE, ( xt -- )\r
1368 \               Optimized COMPILE, . Reduce doLIST ... EXIT sequence if\r
1369 \               xt is COLON definition which contains less than two words.\r
1370 \r
1371 : optiCOMPILE,\r
1372                 DUP ?call ['] doLIST = IF\r
1373                     DUP code@ ['] EXIT = IF         \ if first word is EXIT\r
1374                       2DROP EXIT THEN\r
1375                     DUP CELL+ code@ ['] EXIT = IF   \ if second word is EXIT\r
1376                       code@ DUP ['] doLIT XOR   \ make sure it is not literal\r
1377                       IF SWAP THEN THEN\r
1378                 THEN DROP COMPILE, ;\r
1379 \r
1380 \                 $COLON  NameOptiCOMPILEComma,OptiCOMPILEComma\r
1381 \                 DW      DUPP,QCall,DoLIT,DoLIST,Equals,ZBranch,OPTC2\r
1382 \                 DW      DUPP,CodeFetch,DoLIT,EXIT,Equals,ZBranch,OPTC1\r
1383 \                 DW      TwoDROP,EXIT\r
1384 \ OPTC1           DW      DUPP,CELLPlus,CodeFetch,DoLIT,EXIT,Equals\r
1385 \                 DW      ZBranch,OPTC2\r
1386 \                 DW      CodeFetch,DUPP,DoLIT,DoLIT,XORR,ZBranch,OPTC2\r
1387 \                 DW      SWAP\r
1388 \ OPTC2           DW      DROP,COMPILEComma,EXIT\r
1389 \r
1390 \               $CODE   NameOptiCOMPILEComma,OptiCOMPILEComma\r
1391 \               CMP     WORD PTR CS:[BX],CALLL\r
1392 \               JNE     OPTC1\r
1393 \               MOV     AX,CS:[BX+CELLL]\r
1394 \               ADD     AX,BX\r
1395 \               ADD     AX,2*CELLL\r
1396 \               CMP     AX,OFFSET DoLIST\r
1397 \               JNE     OPTC1\r
1398 \               MOV     DX,OFFSET EXIT\r
1399 \               MOV     AX,CS:[BX+2*CELLL]\r
1400 \               CMP     AX,DX\r
1401 \               JE      OPTC2\r
1402 \               CMP     DX,CS:[BX+3*CELLL]\r
1403 \               JNE     OPTC1\r
1404 \               CMP     AX,OFFSET DoLIT\r
1405 \               JE      OPTC1\r
1406 \               MOV     BX,AX\r
1407 \ OPTC1:                JMP     COMPILEComma\r
1408 \ OPTC2:                POP     BX\r
1409 \               $NEXT\r
1410 \r
1411 \   singleOnly  ( c-addr u -- x )\r
1412 \               Handle the word not found in the search-order. If the string\r
1413 \               is legal, leave a single cell number in interpretation state.\r
1414 \r
1415 : singleOnly\r
1416                 0 DUP 2SWAP OVER C@ [CHAR] -\r
1417                 = DUP >R IF 1 /STRING THEN\r
1418                 >NUMBER IF -13 THROW THEN       \ undefined word\r
1419                 2DROP R> IF NEGATE THEN ;\r
1420 \r
1421 \               $COLON  NameSingleOnly,SingleOnly\r
1422 \               DW      DoLIT,0,DUPP,TwoSWAP,OVER,CFetch,DoLIT,'-'\r
1423 \               DW      Equals,DUPP,ToR,ZBranch,SINGLEO4\r
1424 \               DW      DoLIT,1,SlashSTRING\r
1425 \ SINGLEO4      DW      ToNUMBER,ZBranch,SINGLEO1\r
1426 \               DW      DoLIT,-13,THROW\r
1427 \ SINGLEO1      DW      TwoDROP,RFrom,ZBranch,SINGLEO2\r
1428 \               DW      NEGATE\r
1429 \ SINGLEO2      DW      EXIT \r
1430 \   singleOnly, ( c-addr u -- )\r
1431 \               Handle the word not found in the search-order. Compile a\r
1432 \               single cell number in compilation state.\r
1433 \r
1434 : singleOnly,\r
1435                 singleOnly POSTPONE LITERAL ;\r
1436 \r
1437 \               $COLON  NameSingleOnlyComma,SingleOnlyComma\r
1438 \               DW      SingleOnly,LITERAL,EXIT\r
1439 \r
1440 \   (doubleAlso) ( c-addr u -- x 1 | x x 2 )\r
1441 \               If the string is legal, leave a single or double cell number\r
1442 \               and size of the number.\r
1443 \r
1444 : (doubleAlso)\r
1445                 0 DUP 2SWAP OVER C@ [CHAR] -\r
1446                 = DUP >R IF 1 /STRING THEN\r
1447                 >NUMBER ?DUP\r
1448                 IF   1- IF -13 THROW THEN     \ more than one char is remained\r
1449                      DUP C@ [CHAR] . XOR      \ last char is not '.'\r
1450                      IF -13 THROW THEN        \ undefined word\r
1451                      R> IF DNEGATE THEN\r
1452                      2 EXIT               THEN\r
1453                 2DROP R> IF NEGATE THEN       \ single number\r
1454                 1 ;\r
1455 \r
1456 \               $COLON  NameParenDoubleAlso,ParenDoubleAlso\r
1457 \               DW      DoLIT,0,DUPP,TwoSWAP,OVER,CFetch,DoLIT,'-'\r
1458 \               DW      Equals,DUPP,ToR,ZBranch,DOUBLEA1\r
1459 \               DW      DoLIT,1,SlashSTRING\r
1460 \ DOUBLEA1      DW      ToNUMBER,QuestionDUP,ZBranch,DOUBLEA4\r
1461 \               DW      OneMinus,ZBranch,DOUBLEA3\r
1462 \ DOUBLEA2      DW      DoLIT,-13,THROW\r
1463 \ DOUBLEA3      DW      CFetch,DoLIT,'.',Equals,ZBranch,DOUBLEA2\r
1464 \               DW      RFrom,ZBranch,DOUBLEA5\r
1465 \               DW      DNEGATE\r
1466 \ DOUBLEA5      DW      DoLIT,2,EXIT\r
1467 \ DOUBLEA4      DW      TwoDROP,RFrom,ZBranch,DOUBLEA6\r
1468 \               DW      NEGATE\r
1469 \ DOUBLEA6      DW      DoLIT,1,EXIT\r
1470 \r
1471 \   doubleAlso  ( c-addr u -- x | x x )\r
1472 \               Handle the word not found in the search-order. If the string\r
1473 \               is legal, leave a single or double cell number in\r
1474 \               interpretation state.\r
1475 \r
1476 : doubleAlso\r
1477                 (doubleAlso) DROP ;\r
1478 \r
1479 \               $COLON  NameDoubleAlso,DoubleAlso\r
1480 \               DW      ParenDoubleAlso,DROP,EXIT\r
1481 \r
1482 \   doubleAlso, ( c-addr u -- )\r
1483 \               Handle the word not found in the search-order. If the string\r
1484 \               is legal, compile a single or double cell number in\r
1485 \               compilation state.\r
1486 \r
1487 : doubleAlso,\r
1488                 (doubleAlso) 1- IF SWAP POSTPONE LITERAL THEN POSTPONE LITERAL ;\r
1489 \r
1490 \               $COLON  NameDoubleAlsoComma,DoubleAlsoComma\r
1491 \               DW      ParenDoubleAlso,OneMinus,ZBranch,DOUBC1\r
1492 \               DW      SWAP,LITERAL\r
1493 \ DOUBC1                DW      LITERAL,EXIT\r
1494 \r
1495 \   -.          ( -- )\r
1496 \               You don't need this word unless you care that '-.' returns\r
1497 \               double cell number 0. Catching illegal number '-.' in this way\r
1498 \               is easier than make 'interpret' catch this exception.\r
1499 \r
1500 : -.            -13 THROW ; IMMEDIATE   \ undefined word\r
1501 \r
1502 \               $COLON  NameMinusDot,MinusDot\r
1503 \               DW      DoLIT,-13,THROW\r
1504 \r
1505 \   lastName    ( -- c-addr )\r
1506 \               Return the address of the last definition name.\r
1507 \r
1508 \               $VALUE  NameLastName,LastName,AddrLastName\r
1509 \r
1510 \   linkLast    ( -- )\r
1511 \               Link the word being defined to the current wordlist.\r
1512 \               Do nothing if the last definition is made by :NONAME .\r
1513 \r
1514 : linkLast      lastName  GET-CURRENT ! ;\r
1515 \r
1516 \                 $COLON  NameLinkLast,LinkLast\r
1517 \                 DW      LastName,GET_CURRENT,Store,EXIT\r
1518 \r
1519 \               $CODE   NameLinkLast,LinkLast\r
1520 \               MOV     AX,AddrLastName\r
1521 \               MOV     DI,AddrCurrent\r
1522 \               MOV     [DI],AX\r
1523 \               $NEXT\r
1524 \r
1525 \   name>xt     ( c-addr -- xt )\r
1526 \               Return execution token using counted string at c-addr.\r
1527 \r
1528 : name>xt               cell- cell- @ ;\r
1529 \r
1530 \                 $COLON  NameNameToXT,NameToXT\r
1531 \                 DW      CellMinus,CellMinus,Fetch,EXIT\r
1532 \r
1533 \               $CODE   NameNameToXT,NameToXT\r
1534 \               MOV     BX,[BX-2*CELLL]\r
1535 \               $NEXT\r
1536 \r
1537 \   pack"       ( c-addr u a-addr -- a-addr2 )\r
1538 \               Place a string c-addr u at a-addr and gives the next\r
1539 \               cell-aligned address. Fill the rest of the last cell with\r
1540 \               null character.\r
1541 \r
1542 : pack"         2DUP SWAP CHARS + CHAR+ DUP >R  \ ca u aa aa+u+1\r
1543                 ALIGNED cell- 0 SWAP !          \ fill 0 at the end of string\r
1544                 2DUP C! CHAR+ SWAP              \ c-addr a-addr+1 u\r
1545                 CHARS MOVE R> ALIGNED ;\r
1546 \r
1547 \                 $COLON  5,'pack"',PackQuote,_SLINK\r
1548 \                 DW      TwoDUP,SWAP,CHARS,Plus,CHARPlus,DUPP,ToR\r
1549 \                 DW      ALIGNED,CellMinus,Zero,SWAP,Store\r
1550 \                 DW      TwoDUP,CStore,CHARPlus,SWAP\r
1551 \                 DW      CHARS,MOVE,RFrom,ALIGNED,EXIT\r
1552 \r
1553 \               $CODE   NamePackQuote,PackQuote\r
1554 \               MOV     DI,BX\r
1555 \               MOV     DX,SI\r
1556 \               MOV     AX,DS\r
1557 \               MOV     ES,AX\r
1558 \               POP     CX\r
1559 \               POP     SI\r
1560 \               MOV     BYTE PTR [DI],CL\r
1561 \               INC     DI\r
1562 \               REP MOVSB\r
1563 \               TEST    DI,1            ;odd address?\r
1564 \               JZ      PACKQ2\r
1565 \               MOV     BYTE PTR [DI],0\r
1566 \               INC     DI\r
1567 \ PACKQ2:       MOV     BX,DI\r
1568 \               MOV     SI,DX\r
1569 \               $NEXT\r
1570 \r
1571 \   PARSE-WORD  ( "<spaces>ccc<space>" -- c-addr u )\r
1572 \               Skip leading spaces and parse a word. Return the name.\r
1573 \r
1574 : PARSE-WORD    BL skipPARSE ;\r
1575 \r
1576 \                 $COLON  NamePARSE_WORD,PARSE_WORD\r
1577 \                 DW      DoLIT,' ',SkipPARSE,EXIT\r
1578 \r
1579 \               $CODE   NamePARSE_WORD,PARSE_WORD\r
1580 \               PUSH    BX\r
1581 \               MOV     BX,' '\r
1582 \               JMP     SkipPARSE\r
1583 \               $ALIGN\r
1584 \r
1585 \   pipe        ( -- ) ( R: xt -- )\r
1586 \               Connect most recently defined word to code following DOES>.\r
1587 \               Structure of CREATEd word:\r
1588 \               |compile_xt|name_ptr| call-doCREATE | 0 or DOES>_xt | a-addr |\r
1589 \r
1590 : pipe          lastName name>xt ?call DUP IF   \ code-addr xt2\r
1591                     ['] doCREATE = IF\r
1592                     R> SWAP code!       \ change DOES> code of CREATEd word\r
1593                     EXIT\r
1594                 THEN THEN\r
1595                 -32 THROW       \ invalid name argument, no-CREATEd last name\r
1596                 ; COMPILE-ONLY\r
1597 \r
1598 \               $COLON  NamePipe,Pipe\r
1599 \               DW      LastName,NameToXT,QCall,DUPP,ZBranch,PIPE1\r
1600 \               DW      DoLIT,DoCREATE,Equals,ZBranch,PIPE1\r
1601 \               DW      RFrom,SWAP,CodeStore,EXIT\r
1602 \ PIPE1         DW      DoLIT,-32,THROW\r
1603 \r
1604 \   skipPARSE   ( char "<chars>ccc<char>" -- c-addr u )\r
1605 \               Skip leading chars and parse a word using char as a\r
1606 \               delimeter. Return the name.\r
1607 \r
1608 : skipPARSE\r
1609                 >R SOURCE >IN @ /STRING    \ c_addr u  R: char\r
1610                 DUP IF\r
1611                    BEGIN  OVER C@ R@ =\r
1612                    WHILE  1- SWAP CHAR+ SWAP DUP 0=\r
1613                    UNTIL  R> DROP EXIT\r
1614                    ELSE THEN\r
1615                    DROP SOURCE DROP - 1chars/ >IN ! R> PARSE EXIT\r
1616                 THEN R> DROP ;\r
1617 \r
1618 \                 $COLON  NameSkipPARSE,SkipPARSE\r
1619 \                 DW      ToR,SOURCE,DoLIT,AddrToIN,Fetch,SlashSTRING\r
1620 \                 DW      DUPP,ZBranch,SKPAR1\r
1621 \ SKPAR2          DW      OVER,CFetch,RFetch,Equals,ZBranch,SKPAR3\r
1622 \                 DW      OneMinus,SWAP,CHARPlus,SWAP\r
1623 \                 DW      DUPP,ZeroEquals,ZBranch,SKPAR2\r
1624 \                 DW      RFrom,DROP,EXIT\r
1625 \ SKPAR3          DW      DROP,SOURCE,DROP,Minus,OneCharsSlash\r
1626 \                 DW      DoLIT,AddrToIN,Store,RFrom,PARSE,EXIT\r
1627 \ SKPAR1          DW      RFrom,DROP,EXIT\r
1628 \r
1629 \               $CODE   NameSkipPARSE,SkipPARSE\r
1630 \               MOV     AH,BL\r
1631 \               MOV     DX,SI\r
1632 \               MOV     SI,AddrSourceVar+CELLL\r
1633 \               MOV     BX,AddrSourceVar\r
1634 \               MOV     CX,AddrToIN\r
1635 \               ADD     SI,CX\r
1636 \               SUB     BX,CX\r
1637 \               MOV     CX,SI\r
1638 \               OR      BX,BX\r
1639 \               JZ      PARSW1\r
1640 \ PARSW5:       LODSB\r
1641 \               CMP     AL,AH\r
1642 \               JNE     PARSW4\r
1643 \               DEC     BX\r
1644 \               OR      BX,BX\r
1645 \               JNZ     PARSW5\r
1646 \               MOV     AX,AddrSourceVar\r
1647 \               MOV     AddrToIN,AX\r
1648 \ PARSW1:       PUSH    SI\r
1649 \               MOV     SI,DX\r
1650 \               $NEXT\r
1651 \ PARSW4:       DEC     SI\r
1652 \               SUB     SI,AddrSourceVar+CELLL\r
1653 \               MOV     AddrToIN,SI\r
1654 \               XOR     BX,BX\r
1655 \               MOV     BL,AH\r
1656 \               MOV     SI,DX\r
1657 \               JMP     PARSE\r
1658 \               $ALIGN\r
1659 \r
1660 \   specialComp? ( -- xt|0 )\r
1661 \               Return xt for special compilation semantics of the last found\r
1662 \               word. Return 0 if there is no special compilation action.\r
1663 \r
1664 \               $VALUE  NameSpecialCompQ,SpecialCompQ,AddrSpecialCompQ\r
1665 \r
1666 \   rake        ( C: do-sys -- )\r
1667 \               Gathers LEAVEs.\r
1668 \r
1669 : rake          DUP code, rakeVar @\r
1670                 BEGIN  2DUP U<\r
1671                 WHILE  DUP code@ xhere ROT code!\r
1672                 REPEAT rakeVar ! DROP\r
1673                 ?DUP IF                 \ check for ?DO\r
1674                    1 bal+ POSTPONE THEN \ orig type is 1\r
1675                 THEN bal- ; COMPILE-ONLY\r
1676 \r
1677 \               $COLON  Namerake,rake\r
1678 \               DW      DUPP,CodeComma,DoLIT,AddrRakeVar,Fetch\r
1679 \ RAKE1         DW      TwoDUP,ULess,ZBranch,RAKE2\r
1680 \               DW      DUPP,CodeFetch,XHere,ROT,CodeStore,Branch,RAKE1\r
1681 \ RAKE2         DW      DoLIT,AddrRakeVar,Store,DROP\r
1682 \               DW      QuestionDUP,ZBranch,RAKE3\r
1683 \               DW      One,BalPlus,THENN\r
1684 \ RAKE3         DW      BalMinus,EXIT\r
1685 \r
1686 \   rp0         ( -- a-addr )\r
1687 \               Pointer to bottom of the return stack.\r
1688 \r
1689 : rp0           userP @ CELL+ CELL+ @ ;\r
1690 \r
1691 \               $COLON  NameRPZero,RPZero\r
1692 \               DW      DoLIT,AddrUserP,Fetch,CELLPlus,CELLPlus,Fetch,EXIT\r
1693 \r
1694 \   search-word ( c-addr u -- c-addr u 0 | xt f 1 | xt f -1)\r
1695 \               Search dictionary for a match with the given name. Return\r
1696 \               execution token, not-compile-only flag and -1 or 1\r
1697 \               ( IMMEDIATE) if found; c-addr u 0 if not.\r
1698 \r
1699 : search-word\r
1700                 #order @ DUP                    \ not found if #order is 0\r
1701                 IF 0\r
1702                    DO 2DUP                      \ ca u ca u\r
1703                       I CELLS #order CELL+ + @  \ ca u ca u wid\r
1704                       (search-wordlist)         \ ca u; 0 | w f 1 | w f -1\r
1705                       ?DUP IF                   \ ca u; 0 | w f 1 | w f -1\r
1706                          >R 2SWAP 2DROP R> UNLOOP EXIT \ xt f 1 | xt f -1\r
1707                       THEN                      \ ca u\r
1708                    LOOP 0                       \ ca u 0\r
1709                 THEN ;\r
1710 \r
1711 \               $COLON  NameSearch_word,Search_word\r
1712 \               DW      NumberOrder,Fetch,DUPP,ZBranch,SEARCH1\r
1713 \               DW      DoLIT,0,DoDO\r
1714 \ SEARCH2       DW      TwoDUP,I,CELLS,NumberOrder,CELLPlus,Plus,Fetch\r
1715 \               DW      ParenSearch_Wordlist,QuestionDUP,ZBranch,SEARCH3\r
1716 \               DW      ToR,TwoSWAP,TwoDROP,RFrom,UNLOOP,EXIT\r
1717 \ SEARCH3       DW      DoLOOP,SEARCH2\r
1718 \               DW      DoLIT,0\r
1719 \ SEARCH1       DW      EXIT\r
1720 \r
1721 \   sourceVar   ( -- a-addr )\r
1722 \               Hold the current count and address of the terminal input buffer.\r
1723 \r
1724 \               $CONST  NameSourceVar,SourceVar,AddrSourceVar\r
1725 \r
1726 \   sp0         ( -- a-addr )\r
1727 \               Pointer to bottom of the data stack.\r
1728 \r
1729 : sp0           userP @ CELL+ @ ;\r
1730 \r
1731 \               $COLON  NameSPZero,SPZero\r
1732 \               DW      DoLIT,AddrUserP,Fetch,CELLPlus,Fetch,EXIT\r
1733 \r
1734 \ ;;;;;;;;;;;;;;;\r
1735 \ Essential Standard words - Colon definitions\r
1736 \ ;;;;;;;;;;;;;;;\r
1737 \r
1738 \   #           ( ud1 -- ud2 )                  \ CORE\r
1739 \               Extract one digit from ud1 and append the digit to\r
1740 \               pictured numeric output string. ( ud2 = ud1 / BASE )\r
1741 \r
1742 : #             0 BASE @ UM/MOD >R BASE @ UM/MOD SWAP\r
1743                 9 OVER < [ CHAR A CHAR 9 1 + - ] LITERAL AND +\r
1744                 [ CHAR 0 ] LITERAL + HOLD R> ;\r
1745 \r
1746 \                 $COLON  NameNumberSign,NumberSign\r
1747 \                 DW      DoLIT,0,DoLITFetch,AddrBASE,UMSlashMOD,ToR\r
1748 \                 DW      DoLITFetch,AddrBASE,UMSlashMOD,SWAP\r
1749 \                 DW      DoLIT,9,OVER,LessThan,DoLIT,'A'-'9'-1,ANDD,Plus\r
1750 \                 DW      DoLIT,'0',Plus,HOLD,RFrom,EXIT\r
1751 \r
1752 \               $CODE   NameNumberSign,NumberSign\r
1753 \               XOR     DX,DX\r
1754 \               MOV     AX,BX\r
1755 \               MOV     CX,AddrBASE\r
1756 \               DIV     CX              ;0:TOS / BASE\r
1757 \               MOV     BX,AX           ;quotient\r
1758 \               POP     AX\r
1759 \               DIV     CX\r
1760 \               PUSH    AX              ;BX:AX = ud2\r
1761 \               MOV     AL,DL\r
1762 \               CMP     AL,9\r
1763 \               JBE     NUMSN1\r
1764 \               ADD     AL,'A'-'9'-1\r
1765 \ NUMSN1:       ADD     AL,'0'\r
1766 \               MOV     DI,AddrHLD\r
1767 \               DEC     DI\r
1768 \               MOV     AddrHLD,DI\r
1769 \               MOV     [DI],AL\r
1770 \               $NEXT\r
1771 \r
1772 \   #>          ( xd -- c-addr u )              \ CORE\r
1773 \               Prepare the output string to be TYPE'd.\r
1774 \               ||HERE>WORD/#-work-area|\r
1775 \r
1776 : #>            2DROP hld @ HERE size-of-PAD + OVER - 1chars/ ;\r
1777 \r
1778 \               $COLON  NameNumberSignGreater,NumberSignGreater\r
1779 \               DW      TwoDROP,DoLIT,AddrHLD,Fetch,HERE,DoLIT,PADSize*CHARR,Plus\r
1780 \               DW      OVER,Minus,OneCharsSlash,EXIT\r
1781 \r
1782 \   #S          ( ud -- 0 0 )                   \ CORE\r
1783 \               Convert ud until all digits are added to the output string.\r
1784 \r
1785 : #S            BEGIN # 2DUP OR 0= UNTIL ;\r
1786 \r
1787 \               $COLON  NameNumberSignS,NumberSignS\r
1788 \ NUMSS1                DW      NumberSign,TwoDUP,ORR\r
1789 \               DW      ZeroEquals,ZBranch,NUMSS1\r
1790 \               DW      EXIT\r
1791 \r
1792 \   '           ( "<spaces>name" -- xt )        \ CORE\r
1793 \               Parse a name, find it and return xt.\r
1794 \r
1795 : '             (') DROP ;\r
1796 \r
1797 \               $COLON  NameTick,Tick\r
1798 \               DW      ParenTick,DROP,EXIT\r
1799 \r
1800 \   +           ( n1|u1 n2|u2 -- n3|u3 )        \ CORE\r
1801 \               Add top two items and gives the sum.\r
1802 \r
1803 : +             um+ DROP ;\r
1804 \r
1805 \                 $COLON  NamePlus,Plus\r
1806 \                 DW      UMPlus,DROP,EXIT\r
1807 \r
1808 \               $CODE   NamePlus,Plus\r
1809 \               POP     AX\r
1810 \               ADD     BX,AX\r
1811 \               $NEXT\r
1812 \r
1813 \   +!          ( n|u a-addr -- )               \ CORE\r
1814 \               Add n|u to the contents at a-addr.\r
1815 \r
1816 : +!            SWAP OVER @ + SWAP ! ;\r
1817 \r
1818 \                 $COLON  NamePlusStore,PlusStore\r
1819 \                 DW      SWAP,OVER,Fetch,Plus\r
1820 \                 DW      SWAP,Store,EXIT\r
1821 \r
1822 \               $CODE   NamePlusStore,PlusStore\r
1823 \               POP     AX\r
1824 \               ADD     [BX],AX\r
1825 \               POP     BX\r
1826 \               $NEXT\r
1827 \r
1828 \   ,           ( x -- )                        \ CORE\r
1829 \               Reserve one cell in data space and store x in it.\r
1830 \r
1831 : ,             HERE !  HERE CELL+ TO HERE ;\r
1832 \r
1833 \                 $COLON  NameComma,Comma\r
1834 \                 DW      HERE,Store,HERE,CELLPlus,DoTO,AddrHERE,EXIT\r
1835 \r
1836 \               $CODE   NameComma,Comma\r
1837 \               MOV     DI,AddrHERE\r
1838 \               MOV     [DI],BX\r
1839 \               ADD     DI,CELLL\r
1840 \               MOV     AddrHERE,DI\r
1841 \               POP     BX\r
1842 \               $NEXT\r
1843 \r
1844 \   -           ( n1|u1 n2|u2 -- n3|u3 )        \ CORE\r
1845 \               Subtract n2|u2 from n1|u1, giving the difference n3|u3.\r
1846 \r
1847 : -             NEGATE + ;\r
1848 \r
1849 \                 $COLON  NameMinus,Minus\r
1850 \                 DW      NEGATE,Plus,EXIT\r
1851 \\r
1852 \               $CODE   NameMinus,Minus\r
1853 \               POP     AX\r
1854 \               SUB     AX,BX\r
1855 \               MOV     BX,AX\r
1856 \               $NEXT\r
1857 \r
1858 \   .           ( n -- )                        \ CORE\r
1859 \               Display a signed number followed by a space.\r
1860 \r
1861 : .             S>D D. ;\r
1862 \r
1863 \               $COLON  NameDot,Dot\r
1864 \               DW      SToD,DDot,EXIT\r
1865 \r
1866 \   /           ( n1 n2 -- n3 )                 \ CORE\r
1867 \               Divide n1 by n2, giving single-cell quotient n3.\r
1868 \r
1869 : /             /MOD NIP ;\r
1870 \r
1871 \               $COLON  NameSlash,Slash\r
1872 \               DW      SlashMOD,NIP,EXIT\r
1873 \r
1874 \   /MOD        ( n1 n2 -- n3 n4 )              \ CORE\r
1875 \               Divide n1 by n2, giving single-cell remainder n3 and\r
1876 \               single-cell quotient n4.\r
1877 \r
1878 : /MOD          >R S>D R> FM/MOD ;\r
1879 \r
1880 \                 $COLON  NameSlashMOD,SlashMOD\r
1881 \                 DW      ToR,SToD,RFrom,FMSlashMOD,EXIT\r
1882 \r
1883 \               $CODE   NameSlashMOD,SlashMOD\r
1884 \               POP     AX\r
1885 \               CWD\r
1886 \               PUSH    AX\r
1887 \               PUSH    DX\r
1888 \               JMP     FMSlashMOD\r
1889 \               $ALIGN\r
1890 \r
1891 \   /STRING     ( c-addr1 u1 n -- c-addr2 u2 )  \ STRING\r
1892 \               Adjust the char string at c-addr1 by n chars.\r
1893 \r
1894 : /STRING       DUP >R - SWAP R> CHARS + SWAP ;\r
1895 \r
1896 \                 $COLON  NameSlashSTRING,SlashSTRING\r
1897 \                 DW      DUPP,ToR,Minus,SWAP,RFrom,CHARS,Plus,SWAP,EXIT\r
1898 \r
1899 \               $CODE   NameSlashSTRING,SlashSTRING\r
1900 \               POP     AX\r
1901 \               SUB     AX,BX\r
1902 \               POP     DX\r
1903 \               ADD     DX,BX\r
1904 \               PUSH    DX\r
1905 \               MOV     BX,AX\r
1906 \               $NEXT\r
1907 \r
1908 \   1+          ( n1|u1 -- n2|u2 )              \ CORE\r
1909 \               Increase top of the stack item by 1.\r
1910 \r
1911 : 1+            1 + ;\r
1912 \r
1913 \                 $COLON  NameOnePlus,OnePlus\r
1914 \                 DW      DoLIT,1,Plus,EXIT\r
1915 \r
1916 \               $CODE   NameOnePlus,OnePlus\r
1917 \               INC     BX\r
1918 \               $NEXT\r
1919 \r
1920 \   1-          ( n1|u1 -- n2|u2 )              \ CORE\r
1921 \               Decrease top of the stack item by 1.\r
1922 \r
1923 : 1-            -1 + ;\r
1924 \r
1925 \                 $COLON  NameOneMinus,OneMinus\r
1926 \                 DW      DoLIT,-1,Plus,EXIT\r
1927 \r
1928 \               $CODE   NameOneMinus,OneMinus\r
1929 \               DEC     BX\r
1930 \               $NEXT\r
1931 \r
1932 \   2!          ( x1 x2 a-addr -- )             \ CORE\r
1933 \               Store the cell pare x1 x2 at a-addr, with x2 at a-addr and\r
1934 \               x1 at the next consecutive cell.\r
1935 \r
1936 : 2!            SWAP OVER ! CELL+ ! ;\r
1937 \r
1938 \                 $COLON  NameTwoStore,TwoStore\r
1939 \                 DW      SWAP,OVER,Store,CELLPlus,Store,EXIT\r
1940 \\r
1941 \               $CODE   NameTwoStore,TwoStore\r
1942 \               POP     [BX]\r
1943 \               POP     [BX+CELLL]\r
1944 \               POP     BX\r
1945 \               $NEXT\r
1946 \r
1947 \   2@          ( a-addr -- x1 x2 )             \ CORE\r
1948 \               Fetch the cell pair stored at a-addr. x2 is stored at a-addr\r
1949 \               and x1 at the next consecutive cell.\r
1950 \r
1951 : 2@            DUP CELL+ @ SWAP @ ;\r
1952 \r
1953 \                 $COLON  NameTwoFetch,TwoFetch\r
1954 \                 DW      DUPP,CELLPlus,Fetch,SWAP,Fetch,EXIT\r
1955 \r
1956 \               $CODE   NameTwoFetch,TwoFetch\r
1957 \               PUSH    [BX+CELLL]\r
1958 \               MOV     BX,[BX]\r
1959 \               $NEXT\r
1960 \r
1961 \   2DROP       ( x1 x2 -- )                    \ CORE\r
1962 \               Drop cell pair x1 x2 from the stack.\r
1963 \r
1964 : 2DROP         DROP DROP ;\r
1965 \r
1966 \                 $COLON  NameTwoDROP,TwoDROP\r
1967 \                 DW      DROP,DROP,EXIT\r
1968 \r
1969 \               $CODE   NameTwoDROP,TwoDROP\r
1970 \               POP     BX\r
1971 \               POP     BX\r
1972 \               $NEXT\r
1973 \r
1974 \   2DUP        ( x1 x2 -- x1 x2 x1 x2 )        \ CORE\r
1975 \               Duplicate cell pair x1 x2.\r
1976 \r
1977 : 2DUP          OVER OVER ;\r
1978 \r
1979 \                 $COLON  NameTwoDUP,TwoDUP\r
1980 \                 DW      OVER,OVER,EXIT\r
1981 \r
1982 \               $CODE   NameTwoDUP,TwoDUP\r
1983 \               MOV     DI,SP\r
1984 \               PUSH    BX\r
1985 \               PUSH    [DI]\r
1986 \               $NEXT\r
1987 \r
1988 \   2SWAP       ( x1 x2 x3 x4 -- x3 x4 x1 x2 )  \ CORE\r
1989 \               Exchange the top two cell pairs.\r
1990 \r
1991 : 2SWAP         ROT >R ROT R> ;\r
1992 \r
1993 \                 $COLON  NameTwoSWAP,TwoSWAP\r
1994 \                 DW      ROT,ToR,ROT,RFrom,EXIT\r
1995 \r
1996 \               $CODE   NameTwoSWAP,TwoSWAP\r
1997 \               POP     AX\r
1998 \               POP     CX\r
1999 \               POP     DX\r
2000 \               PUSH    AX\r
2001 \               PUSH    BX\r
2002 \               PUSH    DX\r
2003 \               MOV     BX,CX\r
2004 \               $NEXT\r
2005 \r
2006 \   :           ( "<spaces>name" -- colon-sys ) \ CORE\r
2007 \               Start a new colon definition using next word as its name.\r
2008 \r
2009 : :             xhere ALIGNED CELL+ TO xhere  \ reserve a cell for name pointer\r
2010                 :NONAME ROT head,  -1 TO notNONAME? ;\r
2011 \r
2012 \               $COLON  NameCOLON,COLON\r
2013 \               DW      XHere,ALIGNED,CELLPlus,DoTO,AddrXHere\r
2014 \               DW      ColonNONAME,ROT,HeadComma\r
2015 \               DW      DoLIT,-1,DoTO,AddrNotNONAMEQ,EXIT\r
2016 \r
2017 \   :NONAME     ( -- xt colon-sys )             \ CORE EXT\r
2018 \               Create an execution token xt, enter compilation state and\r
2019 \               start the current definition.\r
2020 \r
2021 : :NONAME       bal IF -29 THROW THEN           \ compiler nesting\r
2022                 ['] doLIST xt, DUP -1\r
2023                 0 TO notNONAME?  1 TO bal  ] ;\r
2024                 IMMEDIATE\r
2025 \r
2026 \               $COLON  NameColonNONAME,ColonNONAME\r
2027 \               DW      Bal,ZBranch,NONAME1\r
2028 \               DW      DoLIT,-29,THROW\r
2029 \ NONAME1       DW      DoLIT,DoLIST,xtComma,DUPP,DoLIT,-1\r
2030 \               DW      DoLIT,0,DoTO,AddrNotNONAMEQ\r
2031 \               DW      One,DoTO,AddrBal,RightBracket,EXIT\r
2032 \r
2033 \   ;           ( colon-sys -- )                \ CORE\r
2034 \               Terminate a colon definition.\r
2035 \r
2036 : ;             bal 1- IF -22 THROW THEN        \ control structure mismatch\r
2037                 NIP 1+ IF -22 THROW THEN        \ colon-sys type is -1\r
2038                 notNONAME? IF   \ if the last definition is not created by ':'\r
2039                   linkLast  0 TO notNONAME?     \ link the word to wordlist\r
2040                 THEN  POSTPONE EXIT     \ add EXIT at the end of the definition\r
2041                 0 TO bal  POSTPONE [ ; COMPILE-ONLY IMMEDIATE\r
2042 \r
2043 \               $COLON  NameSemicolon,Semicolon\r
2044 \               DW      Bal,OneMinus,ZBranch,SEMI1\r
2045 \               DW      DoLIT,-22,THROW\r
2046 \ SEMI1         DW      NIP,OnePlus,ZBranch,SEMI2\r
2047 \               DW      DoLIT,-22,THROW\r
2048 \ SEMI2         DW      NotNONAMEQ,ZBranch,SEMI3\r
2049 \               DW      LinkLast,DoLIT,0,DoTO,AddrNotNONAMEQ\r
2050 \ SEMI3         DW      DoLIT,EXIT,COMPILEComma\r
2051 \               DW      DoLIT,0,DoTO,AddrBal,LeftBracket,EXIT\r
2052 \r
2053 \   <           ( n1 n2 -- flag )               \ CORE\r
2054 \               Returns true if n1 is less than n2.\r
2055 \r
2056 : <             2DUP XOR 0<             \ same sign?\r
2057                 IF DROP 0< EXIT THEN    \ different signs, true if n1 <0\r
2058                 - 0< ;                  \ same signs, true if n1-n2 <0\r
2059 \r
2060 \                 $COLON  NameLessThan,LessThan\r
2061 \                 DW      TwoDUP,XORR,ZeroLess,ZBranch,LESS1\r
2062 \                 DW      DROP,ZeroLess,EXIT\r
2063 \ LESS1           DW      Minus,ZeroLess,EXIT\r
2064 \r
2065 \               $CODE   NameLessThan,LessThan\r
2066 \               POP     AX\r
2067 \               SUB     AX,BX\r
2068 \               MOV     BX,-1\r
2069 \               JL      LESS1\r
2070 \               INC     BX\r
2071 \ LESS1:                $NEXT\r
2072 \r
2073 \   <#          ( -- )                          \ CORE\r
2074 \               Initiate the numeric output conversion process.\r
2075 \               ||HERE>WORD/#-work-area|\r
2076 \r
2077 : <#            HERE size-of-PAD + hld ! ;\r
2078 \r
2079 \               $COLON  NameLessNumberSign,LessNumberSign\r
2080 \               DW      HERE,DoLIT,PADSize*CHARR,Plus,DoLIT,AddrHLD,Store,EXIT\r
2081 \r
2082 \   =           ( x1 x2 -- flag )               \ CORE\r
2083 \               Return true if top two are equal.\r
2084 \r
2085 : =             XOR 0= ;\r
2086 \r
2087 \                 $COLON  NameEquals,Equals\r
2088 \                 DW      XORR,ZeroEquals,EXIT\r
2089 \r
2090 \               $CODE   NameEquals,Equals\r
2091 \               POP     AX\r
2092 \               CMP     BX,AX\r
2093 \               MOV     BX,-1\r
2094 \               JE      EQUAL1\r
2095 \               INC     BX\r
2096 \ EQUAL1:       $NEXT\r
2097 \r
2098 \   >           ( n1 n2 -- flag )               \ CORE\r
2099 \               Returns true if n1 is greater than n2.\r
2100 \r
2101 : >             SWAP < ;\r
2102 \r
2103 \                 $COLON  NameGreaterThan,GreaterThan\r
2104 \                 DW      SWAP,LessThan,EXIT\r
2105 \r
2106 \               $CODE   NameGreaterThan,GreaterThan\r
2107 \               POP     AX\r
2108 \               SUB     AX,BX\r
2109 \               MOV     BX,-1\r
2110 \               JG      GREAT1\r
2111 \               INC     BX\r
2112 \ GREAT1:       $NEXT\r
2113 \r
2114 \   >IN         ( -- a-addr )\r
2115 \               Hold the character pointer while parsing input stream.\r
2116 \r
2117 \               $CONST  NameToIN,ToIN,AddrToIN\r
2118 \r
2119 \   >NUMBER     ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )    \ CORE\r
2120 \               Add number string's value to ud1. Leaves string of any\r
2121 \               unconverted chars.\r
2122 \r
2123 : >NUMBER       BEGIN  DUP\r
2124                 WHILE  >R  DUP >R C@                    \ ud char  R: u c-addr\r
2125                        DUP [ CHAR 9 1+ ] LITERAL [CHAR] A WITHIN\r
2126                            IF DROP R> R> EXIT THEN\r
2127                        [ CHAR 0 ] LITERAL - 9 OVER <\r
2128                        [ CHAR A CHAR 9 1 + - ] LITERAL AND -\r
2129                        DUP 0 BASE @ WITHIN\r
2130                 WHILE  SWAP BASE @ UM* DROP ROT BASE @ UM* D+ R> R> 1 /STRING\r
2131                 REPEAT DROP R> R>\r
2132                 THEN ;\r
2133 \r
2134 \                 $COLON  NameToNUMBER,ToNUMBER\r
2135 \ TONUM1          DW      DUPP,ZBranch,TONUM3\r
2136 \                 DW      ToR,DUPP,ToR,CFetch,DUPP\r
2137 \                 DW      DoLIT,'9'+1,DoLIT,'A',WITHIN,ZeroEquals,ZBranch,TONUM2\r
2138 \                 DW      DoLIT,'0',Minus,DoLIT,9,OVER,LessThan\r
2139 \                 DW      DoLIT,'A'-'9'-1,ANDD,Minus,DUPP\r
2140 \                 DW      DoLIT,0,DoLIT,AddrBASE,Fetch,WITHIN,ZBranch,TONUM2\r
2141 \                 DW      SWAP,DoLIT,AddrBASE,Fetch,UMStar,DROP,ROT,DoLIT,AddrBASE,Fetch\r
2142 \                 DW      UMStar,DPlus,RFrom,RFrom,DoLIT,1,SlashSTRING\r
2143 \                 DW      Branch,TONUM1\r
2144 \ TONUM2          DW      DROP,RFrom,RFrom\r
2145 \ TONUM3          DW      EXIT\r
2146 \r
2147 \               $CODE   NameToNUMBER,ToNUMBER\r
2148 \               POP     DI\r
2149 \ TONUM4:       OR      BX,BX\r
2150 \               JZ      TONUM2\r
2151 \               XOR     CX,CX\r
2152 \               MOV     CL,[DI]\r
2153 \               SUB     CX,'0'\r
2154 \               JS      TONUM2          ;not valid digit\r
2155 \               CMP     CX,'9'-'0'\r
2156 \               JLE     TONUM3\r
2157 \               CMP     CX,'A'-'0'\r
2158 \               JL      TONUM2          ;not valid digit\r
2159 \               SUB     CX,'A'-'9'-1\r
2160 \ TONUM3:       CMP     CX,AddrBASE\r
2161 \               JGE     TONUM2          ;not valid digit\r
2162 \               POP     AX\r
2163 \               MUL     AddrBASE\r
2164 \               POP     DX\r
2165 \               PUSH    AX\r
2166 \               MOV     AX,DX\r
2167 \               MUL     AddrBASE\r
2168 \               ADD     AX,CX\r
2169 \               POP     CX\r
2170 \               ADC     DX,CX\r
2171 \               PUSH    AX\r
2172 \               PUSH    DX\r
2173 \               INC     DI\r
2174 \               DEC     BX\r
2175 \               JMP     TONUM4\r
2176 \ TONUM2:       PUSH    DI\r
2177 \               $NEXT\r
2178 \r
2179 \   ?DUP        ( x -- x x | 0 )                \ CORE\r
2180 \               Duplicate top of the stack if it is not zero.\r
2181 \r
2182 : ?DUP          DUP IF DUP THEN ;\r
2183 \r
2184 \                 $COLON  NameQuestionDUP,QuestionDUP\r
2185 \                 DW      DUPP,ZBranch,QDUP1\r
2186 \                 DW      DUPP\r
2187 \ QDUP1           DW      EXIT\r
2188 \r
2189 \               $CODE   NameQuestionDUP,QuestionDUP\r
2190 \               OR      BX,BX\r
2191 \               JZ      QDUP1\r
2192 \               PUSH    BX\r
2193 \ QDUP1:                $NEXT\r
2194 \r
2195 \   ABORT       ( i*x -- ) ( R: j*x -- )        \ EXCEPTION EXT\r
2196 \               Reset data stack and jump to QUIT.\r
2197 \r
2198 : ABORT         -1 THROW ;\r
2199 \r
2200 \               $COLON  NameABORT,ABORT\r
2201 \               DW      DoLIT,-1,THROW\r
2202 \r
2203 \   ACCEPT      ( c-addr +n1 -- +n2 )           \ CORE\r
2204 \               Accept a string of up to +n1 chars. Return with actual count.\r
2205 \               Implementation-defined editing. Stops at EOL# .\r
2206 \               Supports backspace and delete editing.\r
2207 \r
2208 : ACCEPT        >R 0\r
2209                 BEGIN  DUP R@ <                 \ ca n2 f  R: n1\r
2210                 WHILE  EKEY max-char AND\r
2211                        DUP BL <\r
2212                        IF   DUP  cr# = IF ROT 2DROP R> DROP EXIT THEN\r
2213                             DUP  tab# =\r
2214                             IF   DROP 2DUP + BL DUP EMIT SWAP C! 1+\r
2215                             ELSE DUP  bsp# =\r
2216                                  SWAP del# = OR\r
2217                                  IF DROP DUP\r
2218                                         \ discard the last char if not 1st char\r
2219                                  IF 1- bsp# EMIT BL EMIT bsp# EMIT THEN THEN\r
2220                             THEN\r
2221                        ELSE >R 2DUP CHARS + R> DUP EMIT SWAP C! 1+  \ Nick THEN\r
2222                        THEN\r
2223                 REPEAT SWAP  R> 2DROP ;\r
2224 \r
2225 \               $COLON  NameACCEPT,ACCEPT\r
2226 \               DW      ToR,DoLIT,0\r
2227 \ ACCPT1                DW      DUPP,RFetch,LessThan,ZBranch,ACCPT5\r
2228 \               DW      EKEY,DoLIT,MaxChar,ANDD\r
2229 \               DW      DUPP,DoLIT,' ',LessThan,ZBranch,ACCPT3\r
2230 \               DW      DUPP,DoLIT,CRR,Equals,ZBranch,ACCPT4\r
2231 \               DW      ROT,TwoDROP,RFrom,DROP,EXIT\r
2232 \ ACCPT4                DW      DUPP,DoLIT,TABB,Equals,ZBranch,ACCPT6\r
2233 \               DW      DROP,TwoDUP,Plus,DoLIT,' ',DUPP,EMIT,SWAP,CStore,OnePlus\r
2234 \               DW      Branch,ACCPT1\r
2235 \ ACCPT6                DW      DUPP,DoLIT,BKSPP,Equals\r
2236 \               DW      SWAP,DoLIT,DEL,Equals,ORR,ZBranch,ACCPT1\r
2237 \               DW      DUPP,ZBranch,ACCPT1\r
2238 \               DW      OneMinus,DoLIT,BKSPP,EMIT,DoLIT,' ',EMIT,DoLIT,BKSPP,EMIT\r
2239 \               DW      Branch,ACCPT1\r
2240 \ ACCPT3                DW      ToR,TwoDUP,CHARS,Plus,RFrom,DUPP,EMIT,SWAP,CStore\r
2241 \               DW      OnePlus,Branch,ACCPT1\r
2242 \ ACCPT5                DW      SWAP,RFrom,TwoDROP,EXIT\r
2243 \r
2244 \   AGAIN       ( C: dest -- )                  \ CORE EXT\r
2245 \               Resolve backward reference dest. Typically used as\r
2246 \               BEGIN ... AGAIN . Move control to the location specified by\r
2247 \               dest on execution.\r
2248 \r
2249 : AGAIN         IF -22 THROW THEN  \ control structure mismatch; dest type is 0\r
2250                 POSTPONE branch code, bal- ; COMPILE-ONLY IMMEDIATE\r
2251 \r
2252 \               $COLON  NameAGAIN,AGAIN\r
2253 \               DW      ZBranch,AGAIN1\r
2254 \               DW      DoLIT,-22,THROW\r
2255 \ AGAIN1                DW      DoLIT,Branch,COMPILEComma,CodeComma,BalMinus,EXIT\r
2256 \r
2257 \   AHEAD       ( C: -- orig )                  \ TOOLS EXT\r
2258 \               Put the location of a new unresolved forward reference onto\r
2259 \               control-flow stack.\r
2260 \r
2261 : AHEAD         POSTPONE branch xhere 0 code,\r
2262                 1 bal+          \ orig type is 1\r
2263                 ; COMPILE-ONLY IMMEDIATE\r
2264 \r
2265 \               $COLON  NameAHEAD,AHEAD\r
2266 \               DW      DoLIT,Branch,COMPILEComma,XHere,DoLIT,0,CodeComma\r
2267 \               DW      One,BalPlus,EXIT\r
2268 \r
2269 \   BL          ( -- char )                     \ CORE\r
2270 \               Return the value of the blank character.\r
2271 \r
2272 : BL            blank-char-value EXIT ;\r
2273 \r
2274 \               $CONST NameBLank,BLank,' '\r
2275 \r
2276 \   CATCH       ( i*x xt -- j*x 0 | i*x n )     \ EXCEPTION\r
2277 \               Push an exception frame on the exception stack and then execute\r
2278 \               the execution token xt in such a way that control can be\r
2279 \               transferred to a point just after CATCH if THROW is executed\r
2280 \               during the execution of xt.\r
2281 \r
2282 : CATCH         sp@ >R throwFrame @ >R          \ save error frame\r
2283                 rp@ throwFrame !  EXECUTE       \ execute\r
2284                 R> throwFrame !                 \ restore error frame\r
2285                 R> DROP  0 ;                    \ no error\r
2286 \r
2287 \               $COLON  NameCATCH,CATCH\r
2288 \               DW      SPFetch,ToR,ThrowFrame,Fetch,ToR\r
2289 \               DW      RPFetch,ThrowFrame,Store,EXECUTE\r
2290 \               DW      RFrom,ThrowFrame,Store\r
2291 \               DW      RFrom,DROP,DoLIT,0,EXIT\r
2292 \r
2293 \   CELL+       ( a-addr1 -- a-addr2 )          \ CORE\r
2294 \               Return next aligned cell address.\r
2295 \r
2296 : CELL+         cell-size + ;\r
2297 \r
2298 \                 $COLON  NameCELLPlus,CELLPlus\r
2299 \                 DW      DoLIT,CELLL,Plus,EXIT\r
2300 \r
2301 \               $CODE   NameCELLPlus,CELLPlus\r
2302 \               ADD     BX,CELLL\r
2303 \               $NEXT\r
2304 \r
2305 \   CHAR+       ( c-addr1 -- c-addr2 )          \ CORE\r
2306 \               Returns next character-aligned address.\r
2307 \r
2308 : CHAR+         char-size + ;\r
2309 \r
2310 \                 $COLON  NameCHARPlus,CHARPlus\r
2311 \                 DW      DoLIT,CHARR,Plus,EXIT\r
2312 \r
2313 \               $CODE   NameCHARPlus,CHARPlus\r
2314 \               INC     BX\r
2315 \               $NEXT\r
2316 \r
2317 \   COMPILE,    ( xt -- )                       \ CORE EXT\r
2318 \               Compile the execution token on data stack into current\r
2319 \               colon definition.\r
2320 \               Structure of words with special compilation action\r
2321 \                   for default compilation behavior\r
2322 \               |compile_xt|name_ptr| execution_code |\r
2323 \r
2324 : COMPILE,      DUP specialComp? = IF DUP cell- cell- code@ EXECUTE EXIT THEN\r
2325                 code, ;\r
2326 \r
2327 \                 $COLON  NameCOMPILEComma,COMPILEComma\r
2328 \                 DW      DUPP,SpecialCompQ,Equals,ZBranch,COMPILEC1\r
2329 \                 DW      DUPP,CellMinus,CellMinus,CodeFetch,EXECUTE,EXIT\r
2330 \ COMPILEC1       DW      CodeComma,EXIT\r
2331 \r
2332 \               $CODE   NameCOMPILEComma,COMPILEComma\r
2333 \               CMP     BX,AddrSpecialCompQ\r
2334 \               JE      COMPILEC1\r
2335 \               MOV     DI,AddrXHere\r
2336 \               MOV     CS:[DI],BX\r
2337 \               ADD     DI,CELLL\r
2338 \               POP     BX\r
2339 \               MOV     AddrXHere,DI\r
2340 \               $NEXT\r
2341 \ COMPILEC1:    MOV     AX,CS:[BX-2*CELLL]\r
2342 \               JMP     AX\r
2343 \               $ALIGN\r
2344 \r
2345 \   compileCONST ( xt -- )\r
2346 \               Compile a CONSTANT word of which xt is given.\r
2347 \               Structure of CONSTANT word:\r
2348 \               |compile_xt|name_ptr| call-doCONST | x |\r
2349 \r
2350 : compileCONST\r
2351                 CELL+ CELL+ code@ POSTPONE LITERAL ;\r
2352 \r
2353 \                 $COLON  NameCompileCONST,CompileCONST\r
2354 \                 DW      CELLPlus,CELLPlus,CodeFetch,LITERAL,EXIT\r
2355 \r
2356 \               $CODE   NameCompileCONST,CompileCONST\r
2357 \               MOV     CX,CS:[BX+2*CELLL]\r
2358 \               MOV     DI,AddrXHere\r
2359 \               MOV     AX,OFFSET DoLIT\r
2360 \               MOV     CS:[DI],AX\r
2361 \               MOV     CS:[DI+CELLL],CX\r
2362 \               ADD     DI,2*CELLL\r
2363 \               POP     BX\r
2364 \               MOV     AddrXHere,DI\r
2365 \               $NEXT\r
2366 \r
2367 \   CONSTANT    ( x "<spaces>name" -- )         \ CORE\r
2368 \               name Execution: ( -- x )\r
2369 \               Create a definition for name which pushes x on the stack on\r
2370 \               execution.\r
2371 \r
2372 : CONSTANT      bal IF -29 THROW THEN           \ compiler nesting\r
2373                 xhere ALIGNED TO xhere\r
2374                 ['] compileCONST code,\r
2375                 xhere CELL+ TO xhere\r
2376                 ['] doCONST xt, head,\r
2377                 code, linkLast\r
2378                 lastName [ =seman ] LITERAL OVER @ OR SWAP ! ;\r
2379 \r
2380 \               $COLON  NameCONSTANT,CONSTANT\r
2381 \               DW      Bal,ZBranch,CONST1\r
2382 \               DW      DoLIT,-29,THROW\r
2383 \ CONST1                DW      XHere,ALIGNED,DoTO,AddrXHere\r
2384 \               DW      DoLIT,CompileCONST,CodeComma\r
2385 \               DW      XHere,CELLPlus,DoTO,AddrXHere\r
2386 \               DW      DoLIT,DoCONST,xtComma,HeadComma\r
2387 \               DW      CodeComma,LinkLast\r
2388 \               DW      LastName,DoLIT,SEMAN,OVER,Fetch,ORR,SWAP,Store,EXIT\r
2389 \r
2390 \   COUNT       ( c-addr1 -- c-addr2 u )        \ CORE\r
2391 \               Convert counted string to string specification. c-addr2 is\r
2392 \               the next char-aligned address after c-addr1 and u is the\r
2393 \               contents at c-addr1.\r
2394 \r
2395 : COUNT         DUP CHAR+ SWAP C@ ;\r
2396 \r
2397 \                 $COLON  NameCOUNT,COUNT\r
2398 \                 DW      DUPP,CHARPlus,SWAP,CFetch,EXIT\r
2399 \r
2400 \               $CODE   NameCOUNT,COUNT\r
2401 \               MOV     AX,BX\r
2402 \               INC     AX\r
2403 \               MOV     BL,[BX]\r
2404 \               XOR     BH,BH\r
2405 \               PUSH    AX\r
2406 \               $NEXT\r
2407 \r
2408 \   compileCREATE ( xt -- )\r
2409 \               Compile a CREATEd word of which xt is given.\r
2410 \               Structure of CREATEd word:\r
2411 \               |compile_xt|name_ptr| call-doCREATE | 0 or DOES>_xt | a-addr |\r
2412 \r
2413 : compileCREATE\r
2414                 DUP CELL+ CELL+ code@           \ 0 or DOES>_xt\r
2415                 IF code, EXIT THEN\r
2416                 CELL+ CELL+ CELL+ code@ POSTPONE LITERAL ;\r
2417 \r
2418 \               $COLON  NameCompileCREATE,CompileCREATE\r
2419 \               DW      DUPP,CELLPlus,CELLPlus,CodeFetch,ZBranch,COMPCREAT1\r
2420 \               DW      CodeComma,EXIT\r
2421 \ COMPCREAT1    DW      CELLPlus,CELLPlus,CELLPlus,CodeFetch,LITERAL,EXIT\r
2422 \r
2423 \   CREATE      ( "<spaces>name" -- )           \ CORE\r
2424 \               name Execution: ( -- a-addr )\r
2425 \               Create a data object in RAM/ROM data space, which return\r
2426 \               data object address on execution\r
2427 \r
2428 : CREATE        bal IF -29 THROW THEN           \ compiler nesting\r
2429                 xhere ALIGNED TO xhere\r
2430                 ['] compileCREATE code,\r
2431                 xhere CELL+ TO xhere    \ reserve space for nfa\r
2432                 ['] doCREATE xt, head,\r
2433                 0 code,                 \ no DOES> code yet\r
2434                 ALIGN HERE code,        \ >BODY returns this address\r
2435                 linkLast                \ link CREATEd word to current wordlist\r
2436                 lastName [ =seman ] LITERAL OVER @ OR SWAP ! ;\r
2437 \r
2438 \               $COLON  NameCREATE,CREATE\r
2439 \               DW      Bal,ZBranch,CREAT1\r
2440 \               DW      DoLIT,-29,THROW\r
2441 \ CREAT1                DW      XHere,ALIGNED,DoTO,AddrXHere\r
2442 \               DW      DoLIT,CompileCREATE,CodeComma\r
2443 \               DW      XHere,CELLPlus,DoTO,AddrXHere\r
2444 \               DW      DoLIT,DoCREATE,xtComma,HeadComma,DoLIT,0,CodeComma\r
2445 \               DW      ALIGNN,HERE,CodeComma,LinkLast\r
2446 \               DW      LastName,DoLIT,SEMAN,OVER,Fetch,ORR,SWAP,Store,EXIT\r
2447 \r
2448 \   D+          ( d1|ud1 d2|ud2 -- d3|ud3 )     \ DOUBLE\r
2449 \               Add double-cell numbers.\r
2450 \r
2451 : D+            >R SWAP >R um+ R> R> + + ;\r
2452 \r
2453 \                 $COLON  NameDPlus,DPlus\r
2454 \                 DW      ToR,SWAP,ToR,UMPlus\r
2455 \                 DW      RFrom,RFrom,Plus,Plus,EXIT\r
2456 \r
2457 \               $CODE   NameDPlus,DPlus\r
2458 \               POP     CX\r
2459 \               POP     DX\r
2460 \               POP     AX\r
2461 \               ADD     CX,AX\r
2462 \               ADC     BX,DX\r
2463 \               PUSH    CX\r
2464 \               $NEXT\r
2465 \r
2466 \   D.          ( d -- )                        \ DOUBLE\r
2467 \               Display d in free field format followed by a space.\r
2468 \r
2469 : D.            (d.) TYPE SPACE ;\r
2470 \r
2471 \               $COLON  NameDDot,DDot\r
2472 \               DW      ParenDDot,TYPEE,SPACE,EXIT\r
2473 \r
2474 \   DECIMAL     ( -- )                          \ CORE\r
2475 \               Set the numeric conversion radix to decimal 10.\r
2476 \r
2477 : DECIMAL       10 BASE ! ;\r
2478 \r
2479 \               $COLON  NameDECIMAL,DECIMAL\r
2480 \               DW      DoLIT,10,DoLIT,AddrBASE,Store,EXIT\r
2481 \r
2482 \   DEPTH       ( -- +n )                       \ CORE\r
2483 \               Return the depth of the data stack.\r
2484 \r
2485 : DEPTH         sp@ sp0 SWAP - cell-size / ;\r
2486 \r
2487 \                 $COLON  NameDEPTH,DEPTH\r
2488 \                 DW      SPFetch,SPZero,SWAP,Minus\r
2489 \                 DW      DoLIT,CELLL,Slash,EXIT\r
2490 \r
2491 \               $CODE   NameDEPTH,DEPTH\r
2492 \               PUSH    BX\r
2493 \               MOV     BX,AddrUserP\r
2494 \               MOV     BX,[BX+CELLL]\r
2495 \               SUB     BX,SP\r
2496 \               SAR     BX,1\r
2497 \               $NEXT\r
2498 \r
2499 \   DNEGATE     ( d1 -- d2 )                    \ DOUBLE\r
2500 \               Two's complement of double-cell number.\r
2501 \r
2502 : DNEGATE       INVERT >R INVERT 1 um+ R> + ;\r
2503 \r
2504 \                 $COLON  NameDNEGATE,DNEGATE\r
2505 \                 DW      INVERT,ToR,INVERT\r
2506 \                 DW      DoLIT,1,UMPlus\r
2507 \                 DW      RFrom,Plus,EXIT\r
2508 \r
2509 \               $CODE   NameDNEGATE,DNEGATE\r
2510 \               POP     AX\r
2511 \               NEG     AX\r
2512 \               PUSH    AX\r
2513 \               ADC     BX,0\r
2514 \               NEG     BX\r
2515 \               $NEXT\r
2516 \r
2517 \   EKEY        ( -- u )                        \ FACILITY EXT\r
2518 \               Receive one keyboard event u.\r
2519 \r
2520 : EKEY          BEGIN PAUSE EKEY? UNTIL 'ekey EXECUTE ;\r
2521 \r
2522 \               $COLON  NameEKEY,EKEY\r
2523 \ EKEY1         DW      PAUSE,EKEYQuestion,ZBranch,EKEY1\r
2524 \               DW      TickEKEY,EXECUTE,EXIT\r
2525 \r
2526 \   EMIT        ( x -- )                        \ CORE\r
2527 \               Send a character to the output device.\r
2528 \r
2529 : EMIT          'emit EXECUTE ;\r
2530 \r
2531 \                 $COLON  NameEMIT,EMIT\r
2532 \                 DW      TickEMIT,EXECUTE,EXIT\r
2533 \r
2534 \               $CODE   NameEMIT,EMIT\r
2535 \               MOV     AX,AddrTickEMIT\r
2536 \               JMP     AX\r
2537 \               $ALIGN\r
2538 \r
2539 \   FM/MOD      ( d n1 -- n2 n3 )               \ CORE\r
2540 \               Signed floored divide of double by single. Return mod n2\r
2541 \               and quotient n3.\r
2542 \r
2543 : FM/MOD        DUP >R 2DUP XOR >R >R DUP 0< IF DNEGATE THEN\r
2544                 R@ ABS UM/MOD DUP 0<\r
2545                 IF DUP [ 16 BASE ! ] 8000 [ DECIMAL ] XOR IF -11 THROW THEN THEN \ result out of range\r
2546                 SWAP R> 0< IF NEGATE THEN\r
2547                 SWAP R> 0< IF NEGATE OVER IF R@ ROT - SWAP 1- THEN THEN\r
2548                 R> DROP ;\r
2549 \r
2550 \                 $COLON  6,'FM/MOD',FMSlashMOD,_FLINK\r
2551 \                 DW      DUPP,ToR,TwoDUP,XORR,ToR,ToR,DUPP,ZeroLess\r
2552 \                 DW      ZBranch,FMMOD1\r
2553 \                 DW      DNEGATE\r
2554 \ FMMOD1          DW      RFetch,ABSS,UMSlashMOD,DUPP,ZeroLess,ZBranch,FMMOD2\r
2555 \                 DW      DUPP,DoLIT,08000h,XORR,ZBranch,FMMOD2\r
2556 \                 DW      DoLIT,-11,THROW\r
2557 \ FMMOD2          DW      SWAP,RFrom,ZeroLess,ZBranch,FMMOD3\r
2558 \                 DW      NEGATE\r
2559 \ FMMOD3          DW      SWAP,RFrom,ZeroLess,ZBranch,FMMOD4\r
2560 \                 DW      NEGATE,OVER,ZBranch,FMMOD4\r
2561 \                 DW      RFetch,ROT,Minus,SWAP,OneMinus\r
2562 \ FMMOD4          DW      RFrom,DROP,EXIT\r
2563 \r
2564 \               $CODE   NameFMSlashMOD,FMSlashMOD\r
2565 \               POP     DX\r
2566 \               POP     AX\r
2567 \               OR      DX,DX\r
2568 \               JS      FMMOD2\r
2569 \               OR      BX,BX\r
2570 \               JZ      FMMOD1\r
2571 \               JS      FMMOD3\r
2572 \               CMP     DX,BX\r
2573 \               JAE     FMMOD6\r
2574 \               DIV     BX              ;positive dividend, positive divisor\r
2575 \               CMP     AX,08000h\r
2576 \               JA      FMMOD6\r
2577 \               PUSH    DX\r
2578 \               MOV     BX,AX\r
2579 \               $NEXT\r
2580 \ FMMOD3:       NEG     BX              ;positive dividend, negative divisor\r
2581 \               CMP     DX,BX\r
2582 \               JAE     FMMOD6\r
2583 \               DIV     BX\r
2584 \               CMP     AX,08000h\r
2585 \               JA      FMMOD6\r
2586 \               OR      DX,DX\r
2587 \               JZ      FMMOD7          ;modulo = 0\r
2588 \               SUB     DX,BX\r
2589 \               NOT     AX              ;AX=-AX-1\r
2590 \               PUSH    DX\r
2591 \               MOV     BX,AX\r
2592 \               $NEXT\r
2593 \ FMMOD2:       NEG     AX              ;DNEGATE\r
2594 \               ADC     DX,0\r
2595 \               NEG     DX\r
2596 \               OR      BX,BX\r
2597 \               JZ      FMMOD1\r
2598 \               JS      FMMOD4\r
2599 \               CMP     DX,BX           ;negative dividend, positive divisor\r
2600 \               JAE     FMMOD6\r
2601 \               DIV     BX\r
2602 \               CMP     AX,08000h\r
2603 \               JA      FMMOD6\r
2604 \               OR      DX,DX\r
2605 \               JZ      FMMOD7\r
2606 \               SUB     BX,DX\r
2607 \               NOT     AX              ;AX=-AX-1\r
2608 \               PUSH    BX\r
2609 \               MOV     BX,AX\r
2610 \               $NEXT\r
2611 \ FMMOD7:       NEG     AX\r
2612 \               PUSH    DX\r
2613 \               MOV     BX,AX\r
2614 \               $NEXT\r
2615 \ FMMOD4:       NEG     BX              ;negative dividend, negative divisor\r
2616 \               CMP     DX,BX\r
2617 \               JAE     FMMOD6\r
2618 \               DIV     BX\r
2619 \               CMP     AX,08000h\r
2620 \               JA      FMMOD6\r
2621 \               NEG     DX\r
2622 \               MOV     BX,AX\r
2623 \               PUSH    DX\r
2624 \               $NEXT\r
2625 \ FMMOD6:       MOV     BX,-11          ;result out of range\r
2626 \               JMP     THROW\r
2627 \ FMMOD1:       MOV     BX,-10          ;divide by zero\r
2628 \               JMP     THROW\r
2629 \               $ALIGN\r
2630 \r
2631 \   GET-CURRENT   ( -- wid )                    \ SEARCH\r
2632 \               Return the indentifier of the compilation wordlist.\r
2633 \r
2634 : GET-CURRENT   current @ ;\r
2635 \r
2636 \               $COLON  NameGET_CURRENT,GET_CURRENT\r
2637 \               DW      DoLIT,AddrCurrent,Fetch,EXIT\r
2638 \r
2639 \   HOLD        ( char -- )                     \ CORE\r
2640 \               Add char to the beginning of pictured numeric output string.\r
2641 \r
2642 : HOLD          hld @  1 CHARS - DUP hld ! C! ;\r
2643 \r
2644 \                 $COLON  NameHOLD,HOLD\r
2645 \                 DW      DoLIT,AddrHLD,Fetch,DoLIT,0-CHARR,Plus\r
2646 \                 DW      DUPP,DoLIT,AddrHLD,Store,CStore,EXIT\r
2647 \r
2648 \               $CODE   NameHOLD,HOLD\r
2649 \               MOV     DI,AddrHLD\r
2650 \               DEC     DI\r
2651 \               MOV     AddrHLD,DI\r
2652 \               MOV     [DI],BL\r
2653 \               POP     BX\r
2654 \               $NEXT\r
2655 \r
2656 \   I           ( -- n|u ) ( R: loop-sys -- loop-sys )  \ CORE\r
2657 \               Push the innermost loop index.\r
2658 \r
2659 : I             rp@ [ 1 CELLS ] LITERAL + @\r
2660                 rp@ [ 2 CELLS ] LITERAL + @  +  ; COMPILE-ONLY\r
2661 \r
2662 \                 $COLON  NameI,I\r
2663 \                 DW      RPFetch,DoLIT,CELLL,Plus,Fetch\r
2664 \                 DW      RPFetch,DoLIT,2*CELLL,Plus,Fetch,Plus,EXIT\r
2665 \r
2666 \               $CODE   NameI,I\r
2667 \               PUSH    BX\r
2668 \               MOV     BX,[BP]\r
2669 \               ADD     BX,[BP+2]\r
2670 \               $NEXT\r
2671 \r
2672 \   IF          Compilation: ( C: -- orig )             \ CORE\r
2673 \               Run-time: ( x -- )\r
2674 \               Put the location of a new unresolved forward reference orig\r
2675 \               onto the control flow stack. On execution jump to location\r
2676 \               specified by the resolution of orig if x is zero.\r
2677 \r
2678 : IF            POSTPONE 0branch xhere 0 code,\r
2679                 1 bal+ ;                \ orig type is 1\r
2680                 COMPILE-ONLY IMMEDIATE\r
2681 \r
2682 \               $COLON  NameIFF,IFF\r
2683 \               DW      DoLIT,ZBranch,COMPILEComma,XHere,DoLIT,0,CodeComma\r
2684 \               DW      One,BalPlus,EXIT\r
2685 \r
2686 \   INVERT      ( x1 -- x2 )                    \ CORE\r
2687 \               Return one's complement of x1.\r
2688 \r
2689 : INVERT        -1 XOR ;\r
2690 \r
2691 \                 $COLON  NameINVERT,INVERT\r
2692 \                 DW      DoLIT,-1,XORR,EXIT\r
2693 \r
2694 \               $CODE   NameINVERT,INVERT\r
2695 \               NOT     BX\r
2696 \               $NEXT\r
2697 \r
2698 \   KEY         ( -- char )                     \ CORE\r
2699 \               Receive a character. Do not display char.\r
2700 \r
2701 : KEY           EKEY max-char AND ;\r
2702 \r
2703 \               $COLON  NameKEY,KEY\r
2704 \               DW      EKEY,DoLIT,MaxChar,ANDD,EXIT\r
2705 \r
2706 \   LITERAL     Compilation: ( x -- )           \ CORE\r
2707 \               Run-time: ( -- x )\r
2708 \               Append following run-time semantics. Put x on the stack on\r
2709 \               execution\r
2710 \r
2711 : LITERAL       POSTPONE doLIT code, ; COMPILE-ONLY IMMEDIATE\r
2712 \r
2713 \               $COLON  NameLITERAL,LITERAL\r
2714 \               DW      DoLIT,DoLIT,COMPILEComma,CodeComma,EXIT\r
2715 \r
2716 \   NEGATE      ( n1 -- n2 )                    \ CORE\r
2717 \               Return two's complement of n1.\r
2718 \r
2719 : NEGATE        INVERT 1+ ;\r
2720 \r
2721 \                 $COLON  NameNEGATE,NEGATE\r
2722 \                 DW      INVERT,OnePlus,EXIT\r
2723 \r
2724 \               $CODE   NameNEGATE,NEGATE\r
2725 \               NEG     BX\r
2726 \               $NEXT\r
2727 \r
2728 \   NIP         ( n1 n2 -- n2 )                 \ CORE EXT\r
2729 \               Discard the second stack item.\r
2730 \r
2731 : NIP           SWAP DROP ;\r
2732 \r
2733 \                 $COLON  NameNIP,NIP\r
2734 \                 DW      SWAP,DROP,EXIT\r
2735 \r
2736 \               $CODE   NameNIP,NIP\r
2737 \               POP     AX\r
2738 \               $NEXT\r
2739 \r
2740 \   PARSE       ( char "ccc<char>"-- c-addr u )         \ CORE EXT\r
2741 \               Scan input stream and return counted string delimited by char.\r
2742 \r
2743 : PARSE         >R  SOURCE >IN @ /STRING        \ c-addr u  R: char\r
2744                 DUP IF\r
2745                    OVER CHARS + OVER       \ c-addr c-addr+u c-addr  R: char\r
2746                    BEGIN  DUP C@ R@ XOR\r
2747                    WHILE  CHAR+ 2DUP =\r
2748                    UNTIL  DROP OVER - 1chars/ DUP\r
2749                    ELSE   NIP  OVER - 1chars/ DUP CHAR+\r
2750                    THEN   >IN +!\r
2751                 THEN   R> DROP EXIT ;\r
2752 \r
2753 \                 $COLON  5,'PARSE',PARSE,_FLINK\r
2754 \                 DW      ToR,SOURCE,DoLIT,AddrToIN,Fetch,SlashSTRING\r
2755 \                 DW      DUPP,ZBranch,PARSE4\r
2756 \                 DW      OVER,CHARS,Plus,OVER\r
2757 \ PARSE1          DW      DUPP,CFetch,RFetch,XORR,ZBranch,PARSE3\r
2758 \                 DW      CHARPlus,TwoDUP,Equals,ZBranch,PARSE1\r
2759 \ PARSE2          DW      DROP,OVER,Minus,DUPP,OneCharsSlash,Branch,PARSE5\r
2760 \ PARSE3          DW      NIP,OVER,Minus,DUPP,OneCharsSlash,CHARPlus\r
2761 \ PARSE5          DW      DoLIT,AddrToIN,PlusStore\r
2762 \ PARSE4          DW      RFrom,DROP,EXIT\r
2763 \r
2764 \               $CODE   NamePARSE,PARSE\r
2765 \               MOV     AH,BL\r
2766 \               MOV     DX,SI\r
2767 \               MOV     SI,AddrSourceVar+CELLL\r
2768 \               MOV     BX,AddrSourceVar\r
2769 \               MOV     CX,AddrToIN\r
2770 \               ADD     SI,CX\r
2771 \               SUB     BX,CX\r
2772 \               MOV     CX,SI\r
2773 \               PUSH    SI\r
2774 \               OR      BX,BX\r
2775 \               JZ      PARSE1\r
2776 \ PARSE5:       LODSB\r
2777 \               CMP     AL,AH\r
2778 \               JE      PARSE4\r
2779 \               DEC     BX\r
2780 \               OR      BX,BX\r
2781 \               JNZ     PARSE5\r
2782 \               MOV     BX,SI\r
2783 \               SUB     SI,AddrSourceVar+CELLL\r
2784 \               SUB     BX,CX\r
2785 \               MOV     AddrToIN,SI\r
2786 \ PARSE1:       MOV     SI,DX\r
2787 \               $NEXT\r
2788 \ PARSE4:       MOV     BX,SI\r
2789 \               SUB     SI,AddrSourceVar+CELLL\r
2790 \               SUB     BX,CX\r
2791 \               DEC     BX\r
2792 \               MOV     AddrToIN,SI\r
2793 \               MOV     SI,DX\r
2794 \               $NEXT\r
2795 \r
2796 \   QUIT        ( -- ) ( R: i*x -- )            \ CORE\r
2797 \               Empty the return stack, store zero in SOURCE-ID, make the user\r
2798 \               input device the input source, and start text interpreter.\r
2799 \r
2800 : QUIT          BEGIN\r
2801                   rp0 rp!  0 TO SOURCE-ID  0 TO bal  POSTPONE [\r
2802                   BEGIN CR REFILL DROP SPACE    \ REFILL returns always true\r
2803                         ['] interpret CATCH ?DUP 0=\r
2804                   WHILE STATE @ 0= IF .prompt THEN\r
2805                   REPEAT\r
2806                   DUP -1 XOR IF                                 \ ABORT\r
2807                   DUP -2 = IF SPACE abort"msg 2@ TYPE    ELSE   \ ABORT"\r
2808                   SPACE errWord 2@ TYPE\r
2809                   SPACE [CHAR] ? EMIT SPACE\r
2810                   DUP -1 -58 WITHIN IF ." Exception # " . ELSE \ undefined exception\r
2811                   CELLS THROWMsgTbl + @ COUNT TYPE       THEN THEN THEN\r
2812                   sp0 sp!\r
2813                 AGAIN ;\r
2814 \r
2815 \               $COLON  NameQUIT,QUIT\r
2816 \ QUIT1         DW      RPZero,RPStore,DoLIT,0,DoTO,AddrSOURCE_ID\r
2817 \               DW      DoLIT,0,DoTO,AddrBal,LeftBracket\r
2818 \ QUIT2         DW      CR,REFILL,DROP,SPACE\r
2819 \               DW      DoLIT,Interpret,CATCH,QuestionDUP,ZeroEquals\r
2820 \               DW      ZBranch,QUIT3\r
2821 \               DW      DoLIT,AddrSTATE,Fetch,ZeroEquals,ZBranch,QUIT2\r
2822 \               DW      DotPrompt,Branch,QUIT2\r
2823 \ QUIT3         DW      DUPP,DoLIT,-1,XORR,ZBranch,QUIT5\r
2824 \               DW      DUPP,DoLIT,-2,Equals,ZBranch,QUIT4\r
2825 \               DW      SPACE,DoLIT,AddrAbortQMsg,TwoFetch,TYPEE,Branch,QUIT5\r
2826 \ QUIT4         DW      SPACE,DoLIT,AddrErrWord,TwoFetch,TYPEE\r
2827 \               DW      SPACE,DoLIT,'?',EMIT,SPACE\r
2828 \               DW      DUPP,DoLIT,-1,DoLIT,-58,WITHIN,ZBranch,QUIT7\r
2829 \               DW      DoLIT,QUITstr\r
2830 \               DW      COUNT,TYPEE,Dot,Branch,QUIT5\r
2831 \ QUIT7         DW      CELLS,DoLIT,AddrTHROWMsgTbl,Plus,Fetch,COUNT,TYPEE\r
2832 \ QUIT5         DW      SPZero,SPStore,Branch,QUIT1\r
2833 \r
2834 \   REFILL      ( -- flag )                     \ CORE EXT\r
2835 \               Attempt to fill the input buffer from the input source. Make\r
2836 \               the result the input buffer, set >IN to zero, and return true\r
2837 \               if successful. Return false if the input source is a string\r
2838 \               from EVALUATE.\r
2839 \r
2840 \ Nick, possible problem here\r
2841 \ : REFILL      SOURCE-ID IF 0 EXIT THEN\r
2842 \               memTop [ size-of-PAD CHARS ] LITERAL - DUP\r
2843 \               size-of-PAD ACCEPT sourceVar 2!\r
2844 \               0 >IN ! -1 ;\r
2845 \r
2846 \               $COLON  NameREFILL,REFILL\r
2847 \               DW      SOURCE_ID,ZBranch,REFIL1\r
2848 \               DW      DoLIT,0,EXIT\r
2849 \ REFIL1                DW      MemTop,DoLIT,0-PADSize*CHARR,Plus,DUPP\r
2850 \               DW      DoLIT,PADSize*CHARR,ACCEPT,DoLIT,AddrSourceVar,TwoStore\r
2851 \               DW      DoLIT,0,DoLIT,AddrToIN,Store,DoLIT,-1,EXIT\r
2852 \r
2853 \   ROT         ( x1 x2 x3 -- x2 x3 x1 )        \ CORE\r
2854 \               Rotate the top three data stack items.\r
2855 \r
2856 : ROT           >R SWAP R> SWAP ;\r
2857 \r
2858 \                 $COLON  NameROT,ROT\r
2859 \                 DW      ToR,SWAP,RFrom,SWAP,EXIT\r
2860 \r
2861 \                $CODE  NameROT,ROT\r
2862 \                POP    AX\r
2863 \                POP    CX\r
2864 \                PUSH   AX\r
2865 \                PUSH   BX\r
2866 \                MOV    BX,CX\r
2867 \                $NEXT\r
2868 \r
2869 \   S>D         ( n -- d )                      \ CORE\r
2870 \               Convert a single-cell number n to double-cell number.\r
2871 \r
2872 : S>D           DUP 0< ;\r
2873 \r
2874 \                 $COLON  NameSToD,SToD\r
2875 \                 DW      DUPP,ZeroLess,EXIT\r
2876 \r
2877 \               $CODE   NameSToD,SToD\r
2878 \               PUSH    BX\r
2879 \               MOV     AX,BX\r
2880 \               CWD\r
2881 \               MOV     BX,DX\r
2882 \               $NEXT\r
2883 \r
2884 \   SEARCH-WORDLIST     ( c-addr u wid -- 0 | xt 1 | xt -1)     \ SEARCH\r
2885 \               Search word list for a match with the given name.\r
2886 \               Return execution token and -1 or 1 ( IMMEDIATE) if found.\r
2887 \               Return 0 if not found.\r
2888 \r
2889 : SEARCH-WORDLIST\r
2890                 (search-wordlist) DUP IF NIP THEN ;\r
2891 \r
2892 \               $COLON  NameSEARCH_WORDLIST,SEARCH_WORDLIST\r
2893 \               DW      ParenSearch_Wordlist,DUPP,ZBranch,SRCHW1\r
2894 \               DW      NIP\r
2895 \ SRCHW1                DW      EXIT\r
2896 \r
2897 \   SIGN        ( n -- )                        \ CORE\r
2898 \               Add a minus sign to the numeric output string if n is negative.\r
2899 \r
2900 : SIGN          0< IF [CHAR] - HOLD THEN ;\r
2901 \r
2902 \                 $COLON  NameSIGN,SIGN\r
2903 \                 DW      ZeroLess,ZBranch,SIGN1\r
2904 \                 DW      DoLIT,'-',HOLD\r
2905 \ SIGN1           DW      EXIT\r
2906 \r
2907 \               $CODE   NameSIGN,SIGN\r
2908 \               OR      BX,BX\r
2909 \               JNS     SIGN1\r
2910 \               MOV     AL,'-'\r
2911 \               MOV     DI,AddrHLD\r
2912 \               DEC     DI\r
2913 \               MOV     AddrHLD,DI\r
2914 \               MOV     [DI],AL\r
2915 \ SIGN1:                POP     BX\r
2916 \               $NEXT\r
2917 \r
2918 \   SOURCE      ( -- c-addr u )                 \ CORE\r
2919 \               Return input buffer string.\r
2920 \r
2921 : SOURCE                sourceVar 2@ ;\r
2922 \r
2923 \               $COLON  NameSOURCE,SOURCE\r
2924 \               DW      DoLIT,AddrSourceVar,TwoFetch,EXIT\r
2925 \r
2926 \   SPACE       ( -- )                          \ CORE\r
2927 \               Send the blank character to the output device.\r
2928 \r
2929 : SPACE         32 EMIT ;\r
2930 \r
2931 \                 $COLON  NameSPACE,SPACE\r
2932 \                 DW      DoLIT,' ',EMIT,EXIT\r
2933 \r
2934 \               $CODE   NameSPACE,SPACE\r
2935 \               PUSH    BX\r
2936 \               MOV     BX,' '\r
2937 \               MOV     AX,AddrTickEMIT\r
2938 \               JMP     AX\r
2939 \               $ALIGN\r
2940 \r
2941 \   STATE       ( -- a-addr )                   \ CORE\r
2942 \               Return the address of a cell containing compilation-state flag\r
2943 \               which is true in compilation state or false otherwise.\r
2944 \r
2945 \               $CONST  NameSTATE,STATE,AddrSTATE\r
2946 \r
2947 \   THEN        Compilation: ( C: orig -- )     \ CORE\r
2948 \               Run-time: ( -- )\r
2949 \               Resolve the forward reference orig.\r
2950 \r
2951 : THEN          1- IF -22 THROW THEN    \ control structure mismatch\r
2952                                         \ orig type is 1\r
2953                 xhere SWAP code! bal- ; COMPILE-ONLY IMMEDIATE\r
2954 \r
2955 \               $COLON  NameTHENN,THENN\r
2956 \               DW      OneMinus,ZBranch,THEN1\r
2957 \               DW      DoLIT,-22,THROW\r
2958 \ THEN1         DW      XHere,SWAP,CodeStore,BalMinus,EXIT\r
2959 \r
2960 \   THROW       ( k*x n -- k*x | i*x n )        \ EXCEPTION\r
2961 \               If n is not zero, pop the topmost exception frame from the\r
2962 \               exception stack, along with everything on the return stack\r
2963 \               above the frame. Then restore the condition before CATCH and\r
2964 \               transfer control just after the CATCH that pushed that\r
2965 \               exception frame.\r
2966 \r
2967 : THROW         ?DUP\r
2968                 IF   throwFrame @ rp!   \ restore return stack\r
2969                      R> throwFrame !    \ restore THROW frame\r
2970                      R> SWAP >R sp!     \ restore data stack\r
2971                      DROP R>\r
2972                      'init-i/o EXECUTE\r
2973                 THEN ;\r
2974 \r
2975 \               $COLON  NameTHROW,THROW\r
2976 \               DW      QuestionDUP,ZBranch,THROW1\r
2977 \               DW      ThrowFrame,Fetch,RPStore,RFrom,ThrowFrame,Store\r
2978 \               DW      RFrom,SWAP,ToR,SPStore,DROP,RFrom\r
2979 \               DW      TickINIT_IO,EXECUTE\r
2980 \ THROW1                DW      EXIT\r
2981 \r
2982 \   TYPE        ( c-addr u -- )                 \ CORE\r
2983 \               Display the character string if u is greater than zero.\r
2984 \r
2985 : TYPE          ?DUP IF 0 DO DUP C@ EMIT CHAR+ LOOP THEN DROP ;\r
2986 \r
2987 \                 $COLON  NameTYPEE,TYPEE\r
2988 \                 DW      QuestionDUP,ZBranch,TYPE2\r
2989 \                 DW      DoLIT,0,DoDO\r
2990 \ TYPE1           DW      DUPP,CFetch,EMIT,CHARPlus,DoLOOP,TYPE1\r
2991 \ TYPE2           DW      DROP,EXIT\r
2992 \r
2993 \               $CODE   NameTYPEE,TYPEE\r
2994 \               POP     DI\r
2995 \               OR      BX,BX\r
2996 \               JZ      TYPE2\r
2997 \               PUSH    SI\r
2998 \               SUB     BP,CELLL\r
2999 \               MOV     [BP],BX\r
3000 \               MOV     BX,DI\r
3001 \ TYPE4:                MOV     DI,BX\r
3002 \               XOR     BX,BX\r
3003 \               MOV     BL,[DI]\r
3004 \               INC     DI\r
3005 \               PUSH    DI\r
3006 \               MOV     SI,OFFSET TYPE3\r
3007 \               MOV     AX,AddrTickEMIT\r
3008 \               JMP     AX\r
3009 \ TYPE1:                DEC     WORD PTR [BP]\r
3010 \               JNZ     TYPE4\r
3011 \               POP     SI\r
3012 \               ADD     BP,CELLL\r
3013 \ TYPE2:                POP     BX\r
3014 \               $NEXT\r
3015 \ TYPE3         DW      TYPE1\r
3016 \r
3017 \   U<          ( u1 u2 -- flag )               \ CORE\r
3018 \               Unsigned compare of top two items. True if u1 < u2.\r
3019 \r
3020 : U<            2DUP XOR 0< IF NIP 0< EXIT THEN - 0< ;\r
3021 \r
3022 \                 $COLON  NameULess,ULess\r
3023 \                 DW      TwoDUP,XORR,ZeroLess\r
3024 \                 DW      ZBranch,ULES1\r
3025 \                 DW      NIP,ZeroLess,EXIT\r
3026 \ ULES1           DW      Minus,ZeroLess,EXIT\r
3027 \r
3028 \               $CODE   NameULess,ULess\r
3029 \               POP     AX\r
3030 \               SUB     AX,BX\r
3031 \               MOV     BX,-1\r
3032 \               JB      ULES1\r
3033 \               INC     BX\r
3034 \ ULES1:                $NEXT\r
3035 \r
3036 \   UM*         ( u1 u2 -- ud )                 \ CORE\r
3037 \               Unsigned multiply. Return double-cell product.\r
3038 \r
3039 : UM*           0 SWAP cell-size-in-bits 0 DO\r
3040                    DUP um+ >R >R DUP um+ R> +\r
3041                    R> IF >R OVER um+ R> + THEN     \ if carry\r
3042                 LOOP ROT DROP ;\r
3043 \r
3044 \                 $COLON  NameUMStar,UMStar\r
3045 \                 DW      DoLIT,0,SWAP,DoLIT,CELLL*8,DoLIT,0,DoDO\r
3046 \ UMST1           DW      DUPP,UMPlus,ToR,ToR\r
3047 \                 DW      DUPP,UMPlus,RFrom,Plus,RFrom\r
3048 \                 DW      ZBranch,UMST2\r
3049 \                 DW      ToR,OVER,UMPlus,RFrom,Plus\r
3050 \ UMST2           DW      DoLOOP,UMST1\r
3051 \                 DW      ROT,DROP,EXIT\r
3052 \r
3053 \               $CODE   NameUMStar,UMStar\r
3054 \               POP     AX\r
3055 \               MUL     BX\r
3056 \               PUSH    AX\r
3057 \               MOV     BX,DX\r
3058 \               $NEXT\r
3059 \r
3060 \   UM/MOD      ( ud u1 -- u2 u3 )              \ CORE\r
3061 \               Unsigned division of a double-cell number ud by a single-cell\r
3062 \               number u1. Return remainder u2 and quotient u3.\r
3063 \r
3064 : UM/MOD        DUP 0= IF -10 THROW THEN        \ divide by zero\r
3065                 2DUP U< IF\r
3066                    NEGATE cell-size-in-bits 0\r
3067                    DO   >R DUP um+ >R >R DUP um+ R> + DUP\r
3068                         R> R@ SWAP >R um+ R> OR\r
3069                         IF >R DROP 1+ R>\r
3070                         ELSE DROP THEN\r
3071                         R>\r
3072                    LOOP DROP SWAP EXIT\r
3073                 ELSE -11 THROW          \ result out of range\r
3074                 THEN ;\r
3075 \r
3076 \                 $COLON  NameUMSlashMOD,UMSlashMOD\r
3077 \                 DW      DUPP,ZBranch,UMM5\r
3078 \                 DW      TwoDUP,ULess,ZBranch,UMM4\r
3079 \                 DW      NEGATE,DoLIT,CELLL*8,DoLIT,0,DoDO\r
3080 \ UMM1            DW      ToR,DUPP,UMPlus,ToR,ToR,DUPP,UMPlus,RFrom,Plus,DUPP\r
3081 \                 DW      RFrom,RFetch,SWAP,ToR,UMPlus,RFrom,ORR,ZBranch,UMM2\r
3082 \                 DW      ToR,DROP,OnePlus,RFrom,Branch,UMM3\r
3083 \ UMM2            DW      DROP\r
3084 \ UMM3            DW      RFrom,DoLOOP,UMM1\r
3085 \                 DW      DROP,SWAP,EXIT\r
3086 \ UMM5            DW      DoLIT,-10,THROW\r
3087 \ UMM4            DW      DoLIT,-11,THROW\r
3088 \r
3089 \               $CODE   NameUMSlashMOD,UMSlashMOD\r
3090 \               OR      BX,BX\r
3091 \               JZ      UMM1\r
3092 \               POP     DX\r
3093 \               CMP     DX,BX\r
3094 \               JAE     UMM2\r
3095 \               POP     AX\r
3096 \               DIV     BX\r
3097 \               PUSH    DX\r
3098 \               MOV     BX,AX\r
3099 \               $NEXT\r
3100 \ UMM1:         MOV     BX,-10          ;divide by zero\r
3101 \               JMP     THROW\r
3102 \ UMM2:         MOV     BX,-11          ;result out of range\r
3103 \               JMP     THROW\r
3104 \               $ALIGN\r
3105 \r
3106 \   UNLOOP      ( -- ) ( R: loop-sys -- )       \ CORE\r
3107 \               Discard loop-control parameters for the current nesting level.\r
3108 \               An UNLOOP is required for each nesting level before the\r
3109 \               definition may be EXITed.\r
3110 \r
3111 : UNLOOP        R> R> R> 2DROP >R ;\r
3112 \r
3113 \                 $COLON  NameUNLOOP,UNLOOP\r
3114 \                 DW      RFrom,RFrom,RFrom,TwoDROP,ToR,EXIT\r
3115 \r
3116 \               $CODE   NameUNLOOP,UNLOOP\r
3117 \               ADD     BP,2*CELLL\r
3118 \               $NEXT\r
3119 \r
3120 \   WITHIN      ( n1|u1 n2|n2 n3|u3 -- flag )   \ CORE EXT\r
3121 \               Return true if (n2|u2<=n1|u1 and n1|u1<n3|u3) or\r
3122 \               (n2|u2>n3|u3 and (n2|u2<=n1|u1 or n1|u1<n3|u3)).\r
3123 \r
3124 : WITHIN        OVER - >R - R> U< ;\r
3125 \r
3126 \                 $COLON  NameWITHIN,WITHIN\r
3127 \                 DW      OVER,Minus,ToR                  ;ul <= u < uh\r
3128 \                 DW      Minus,RFrom,ULess,EXIT\r
3129 \r
3130 \               $CODE   NameWITHIN,WITHIN\r
3131 \               POP     AX\r
3132 \               SUB     BX,AX\r
3133 \               POP     DX\r
3134 \               SUB     DX,AX\r
3135 \               CMP     DX,BX\r
3136 \               MOV     BX,-1\r
3137 \               JB      WITHIN1\r
3138 \               INC     BX\r
3139 \ WITHIN1:      $NEXT\r
3140 \r
3141 \   [           ( -- )                          \ CORE\r
3142 \               Enter interpretation state.\r
3143 \r
3144 : [             0 STATE ! ; COMPILE-ONLY IMMEDIATE\r
3145 \r
3146 \               $COLON  NameLeftBracket,LeftBracket\r
3147 \               DW      DoLIT,0,DoLIT,AddrSTATE,Store,EXIT\r
3148 \r
3149 \   ]           ( -- )                          \ CORE\r
3150 \               Enter compilation state.\r
3151 \r
3152 : ]             -1 STATE ! ;\r
3153 \r
3154 \               $COLON  NameRightBracket,RightBracket\r
3155 \               DW      DoLIT,-1,DoLIT,AddrSTATE,Store,EXIT\r
3156 \r
3157 \ ;;;;;;;;;;;;;;;\r
3158 \ Rest of CORE words and two facility words, EKEY? and EMIT?\r
3159 \ ;;;;;;;;;;;;;;;\r
3160 \       Following definitions can be removed from assembler source and\r
3161 \       can be colon-defined later.\r
3162 \r
3163 \   (           ( "ccc<)>" -- )                 \ CORE\r
3164 \               Ignore following string up to next ) . A comment.\r
3165 \r
3166 : (             [CHAR] ) PARSE 2DROP ; IMMEDIATE\r
3167 \r
3168 \               $COLON  NameParen,Paren\r
3169 \               DW      DoLIT,')',PARSE,TwoDROP,EXIT\r
3170 \r
3171 \   *           ( n1|u1 n2|u2 -- n3|u3 )        \ CORE\r
3172 \               Multiply n1|u1 by n2|u2 giving a single product.\r
3173 \r
3174 : *             UM* DROP ;\r
3175 \r
3176 \                 $COLON  NameStar,Star\r
3177 \                 DW      UMStar,DROP,EXIT\r
3178 \r
3179 \               $CODE   NameStar,Star\r
3180 \               POP     AX\r
3181 \               IMUL    BX\r
3182 \               MOV     BX,AX\r
3183 \               $NEXT\r
3184 \r
3185 \   */          ( n1 n2 n3 -- n4 )              \ CORE\r
3186 \               Multiply n1 by n2 producing double-cell intermediate,\r
3187 \               then divide it by n3. Return single-cell quotient.\r
3188 \r
3189 : */            */MOD NIP ;\r
3190 \r
3191 \               $COLON  NameStarSlash,StarSlash\r
3192 \               DW      StarSlashMOD,NIP,EXIT\r
3193 \r
3194 \   */MOD       ( n1 n2 n3 -- n4 n5 )           \ CORE\r
3195 \               Multiply n1 by n2 producing double-cell intermediate,\r
3196 \               then divide it by n3. Return single-cell remainder and\r
3197 \               single-cell quotient.\r
3198 \r
3199 : */MOD         >R M* R> FM/MOD ;\r
3200 \r
3201 \                 $COLON  NameStarSlashMOD,StarSlashMOD\r
3202 \                 DW      ToR,MStar,RFrom,FMSlashMOD,EXIT\r
3203 \r
3204 \               $CODE   NameStarSlashMOD,StarSlashMOD\r
3205 \               POP     AX\r
3206 \               POP     CX\r
3207 \               IMUL    CX\r
3208 \               PUSH    AX\r
3209 \               PUSH    DX\r
3210 \               JMP     FMSlashMOD\r
3211 \               $ALIGN\r
3212 \r
3213 \   +LOOP       Compilation: ( C: do-sys -- )   \ CORE\r
3214 \               Run-time: ( n -- ) ( R: loop-sys1 -- | loop-sys2 )\r
3215 \               Terminate a DO-+LOOP structure. Resolve the destination of all\r
3216 \               unresolved occurences of LEAVE.\r
3217 \               On execution add n to the loop index. If loop index did not\r
3218 \               cross the boundary between loop_limit-1 and loop_limit,\r
3219 \               continue execution at the beginning of the loop. Otherwise,\r
3220 \               finish the loop.\r
3221 \r
3222 : +LOOP         POSTPONE do+LOOP  rake ; COMPILE-ONLY IMMEDIATE\r
3223 \r
3224 \               $COLON  NamePlusLOOP,PlusLOOP\r
3225 \               DW      DoLIT,DoPLOOP,COMPILEComma,rake,EXIT\r
3226 \r
3227 \   ."          ( "ccc<">" -- )                 \ CORE\r
3228 \               Run-time ( -- )\r
3229 \               Compile an inline string literal to be typed out at run time.\r
3230 \r
3231 : ."            POSTPONE S" POSTPONE TYPE ; COMPILE-ONLY IMMEDIATE\r
3232 \r
3233 \               $COLON  NameDotQuote,DotQuote\r
3234 \               DW      SQuote,DoLIT,TYPEE,COMPILEComma,EXIT\r
3235 \r
3236 \   2OVER       ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )      \ CORE\r
3237 \               Copy cell pair x1 x2 to the top of the stack.\r
3238 \r
3239 : 2OVER         >R >R 2DUP R> R> 2SWAP ;\r
3240 \r
3241 \                 $COLON  NameTwoOVER,TwoOVER\r
3242 \                 DW      ToR,ToR,TwoDUP,RFrom,RFrom,TwoSWAP,EXIT\r
3243 \r
3244 \               $CODE   NameTwoOVER,TwoOVER\r
3245 \               MOV     DI,SP\r
3246 \               PUSH    BX\r
3247 \               PUSH    [DI+2*CELLL]\r
3248 \               MOV     BX,[DI+CELLL]\r
3249 \               $NEXT\r
3250 \r
3251 \   >BODY       ( xt -- a-addr )                \ CORE\r
3252 \               Push data field address of CREATEd word.\r
3253 \r
3254 : >BODY         ?call DUP IF                    \ code-addr xt2\r
3255                     ['] doCREATE = IF           \ should be call-doCREATE\r
3256                     CELL+ code@ EXIT\r
3257                 THEN THEN\r
3258                 -31 THROW ;             \ >BODY used on non-CREATEd definition\r
3259 \r
3260 \               $COLON  NameToBODY,ToBODY\r
3261 \               DW      QCall,DUPP,ZBranch,TBODY1\r
3262 \               DW      DoLIT,DoCREATE,Equals,ZBranch,TBODY1\r
3263 \               DW      CELLPlus,CodeFetch,EXIT\r
3264 \ TBODY1                DW      DoLIT,-31,THROW\r
3265 \r
3266 \   ABORT"      ( "ccc<">" -- )                 \ EXCEPTION EXT\r
3267 \               Run-time ( i*x x1 -- | i*x ) ( R: j*x -- | j*x )\r
3268 \               Conditional abort with an error message.\r
3269 \r
3270 : ABORT"        POSTPONE S" POSTPONE ROT\r
3271                 POSTPONE IF POSTPONE abort"msg POSTPONE 2!\r
3272                 -2 POSTPONE LITERAL POSTPONE THROW\r
3273                 POSTPONE ELSE POSTPONE 2DROP POSTPONE THEN\r
3274                 ;  COMPILE-ONLY IMMEDIATE\r
3275 \r
3276 \               $COLON  NameABORTQuote,ABORTQuote\r
3277 \               DW      SQuote,DoLIT,ROT,COMPILEComma\r
3278 \               DW      IFF,DoLIT,AbortQMsg,COMPILEComma ; IF is immediate\r
3279 \               DW      DoLIT,TwoStore,COMPILEComma\r
3280 \               DW      DoLIT,-2,LITERAL                 ; LITERAL is immediate\r
3281 \               DW      DoLIT,THROW,COMPILEComma\r
3282 \               DW      ELSEE,DoLIT,TwoDROP,COMPILEComma ; ELSE and THEN are\r
3283 \               DW      THENN,EXIT                       ; immediate\r
3284 \r
3285 \   ABS         ( n -- u )                      \ CORE\r
3286 \               Return the absolute value of n.\r
3287 \r
3288 : ABS           DUP 0< IF NEGATE THEN ;\r
3289 \r
3290 \                 $COLON  NameABSS,ABSS\r
3291 \                 DW      DUPP,ZeroLess,ZBranch,ABS1\r
3292 \                 DW      NEGATE\r
3293 \ ABS1            DW      EXIT\r
3294 \r
3295 \               $CODE   NameABSS,ABSS\r
3296 \               OR      BX,BX\r
3297 \               JNS     ABS1\r
3298 \               NEG     BX\r
3299 \ ABS1:         $NEXT\r
3300 \r
3301 \   ALLOT       ( n -- )                        \ CORE\r
3302 \               Allocate n bytes in data space.\r
3303 \r
3304 : ALLOT         HERE + TO HERE ;\r
3305 \r
3306 \               $COLON  NameALLOT,ALLOT\r
3307 \               DW      HERE,Plus,DoTO,AddrHERE,EXIT\r
3308 \r
3309 \   BEGIN       ( C: -- dest )                  \ CORE\r
3310 \               Start an infinite or indefinite loop structure. Put the next\r
3311 \               location for a transfer of control, dest, onto the data\r
3312 \               control stack.\r
3313 \r
3314 : BEGIN         xhere 0 bal+            \ dest type is 0\r
3315                 ; COMPILE-ONLY IMMEDIATE\r
3316 \r
3317 \               $COLON  NameBEGIN,BEGIN\r
3318 \               DW      XHere,DoLIT,0,BalPlus,EXIT\r
3319 \r
3320 \   C,          ( char -- )                     \ CORE\r
3321 \               Compile a character into data space.\r
3322 \r
3323 : C,            HERE C!  HERE CHAR+ TO HERE ;\r
3324 \r
3325 \                 $COLON  NameCComma,CComma\r
3326 \                 DW      HERE,CStore,HERE,CHARPlus,DoTO,AddrHERE,EXIT\r
3327 \r
3328 \               $CODE   NameCComma,CComma\r
3329 \               MOV     DI,AddrHERE\r
3330 \               MOV     [DI],BL\r
3331 \               INC     DI\r
3332 \               MOV     AddrHERE,DI\r
3333 \               POP     BX\r
3334 \               $NEXT\r
3335 \r
3336 \   CHAR        ( "<spaces>ccc" -- char )       \ CORE\r
3337 \               Parse next word and return the value of first character.\r
3338 \r
3339 : CHAR          PARSE-WORD DROP C@ ;\r
3340 \r
3341 \               $COLON  NameCHAR,CHAR\r
3342 \               DW      PARSE_WORD,DROP,CFetch,EXIT\r
3343 \r
3344 \   DO          Compilation: ( C: -- do-sys )   \ CORE\r
3345 \               Run-time: ( n1|u1 n2|u2 -- ) ( R: -- loop-sys )\r
3346 \               Start a DO-LOOP structure in a colon definition. Place do-sys\r
3347 \               on control-flow stack, which will be resolved by LOOP or +LOOP.\r
3348 \r
3349 : DO            0 rakeVar !  0                  \ ?DO-orig is 0 for DO\r
3350                 POSTPONE doDO xhere  bal+ ;     \ DO-dest\r
3351                 COMPILE-ONLY IMMEDIATE\r
3352 \r
3353 \               $COLON  NameDO,DO\r
3354 \               DW      DoLIT,0,RakeVar,Store,DoLIT,0\r
3355 \               DW      DoLIT,DoDO,COMPILEComma,XHere,BalPlus,EXIT\r
3356 \r
3357 \   DOES>       ( C: colon-sys1 -- colon-sys2 ) \ CORE\r
3358 \               Build run time code of the data object CREATEd.\r
3359 \r
3360 : DOES>         bal 1- IF -22 THROW THEN        \ control structure mismatch\r
3361                 NIP 1+ IF -22 THROW THEN        \ colon-sys type is -1\r
3362                 POSTPONE pipe ['] doLIST xt, -1 ; COMPILE-ONLY IMMEDIATE\r
3363 \r
3364 \               $COLON  NameDOESGreater,DOESGreater\r
3365 \               DW      Bal,OneMinus,ZBranch,DOES1\r
3366 \               DW      DoLIT,-22,THROW\r
3367 \ DOES1         DW      NIP,OnePlus,ZBranch,DOES2\r
3368 \               DW      DoLIT,-22,THROW\r
3369 \ DOES2         DW      DoLIT,Pipe,COMPILEComma\r
3370 \               DW      DoLIT,DoLIST,xtComma,DoLIT,-1,EXIT\r
3371 \r
3372 \   ELSE        Compilation: ( C: orig1 -- orig2 )      \ CORE\r
3373 \               Run-time: ( -- )\r
3374 \               Start the false clause in an IF-ELSE-THEN structure.\r
3375 \               Put the location of new unresolved forward reference orig2\r
3376 \               onto control-flow stack.\r
3377 \r
3378 : ELSE          POSTPONE AHEAD 2SWAP POSTPONE THEN ; COMPILE-ONLY IMMEDIATE\r
3379 \r
3380 \               $COLON  NameELSEE,ELSEE\r
3381 \               DW      AHEAD,TwoSWAP,THENN,EXIT\r
3382 \r
3383 \   ENVIRONMENT?   ( c-addr u -- false | i*x true )     \ CORE\r
3384 \               Environment query.\r
3385 \r
3386 : ENVIRONMENT?\r
3387                 envQList SEARCH-WORDLIST\r
3388                 DUP >R IF EXECUTE THEN R> ;\r
3389 \r
3390 \               $COLON  NameENVIRONMENTQuery,ENVIRONMENTQuery\r
3391 \               DW      DoLIT,AddrEnvQList,SEARCH_WORDLIST\r
3392 \               DW      DUPP,ToR,ZBranch,ENVRN1\r
3393 \               DW      EXECUTE\r
3394 \ ENVRN1                DW      RFrom,EXIT\r
3395 \r
3396 \   EVALUATE    ( i*x c-addr u -- j*x )         \ CORE\r
3397 \               Evaluate the string. Save the input source specification.\r
3398 \               Store -1 in SOURCE-ID.\r
3399 \r
3400 : EVALUATE      SOURCE >R >R >IN @ >R  SOURCE-ID >R\r
3401                 -1 TO SOURCE-ID\r
3402                 sourceVar 2!  0 >IN !  interpret\r
3403                 R> TO SOURCE-ID\r
3404                 R> >IN ! R> R> sourceVar 2! ;\r
3405 \r
3406 \               $COLON  NameEVALUATE,EVALUATE\r
3407 \               DW      SOURCE,ToR,ToR,DoLIT,AddrToIN,Fetch,ToR,SOURCE_ID,ToR\r
3408 \               DW      DoLIT,-1,DoTO,AddrSOURCE_ID\r
3409 \               DW      DoLIT,AddrSourceVar,TwoStore,DoLIT,0,DoLIT,AddrToIN,Store,Interpret\r
3410 \               DW      RFrom,DoTO,AddrSOURCE_ID\r
3411 \               DW      RFrom,DoLIT,AddrToIN,Store,RFrom,RFrom,DoLIT,AddrSourceVar,TwoStore,EXIT\r
3412 \r
3413 \   FILL        ( c-addr u char -- )            \ CORE\r
3414 \               Store char in each of u consecutive characters of memory\r
3415 \               beginning at c-addr.\r
3416 \r
3417 : FILL          ROT ROT ?DUP IF 0 DO 2DUP C! CHAR+ LOOP THEN 2DROP ;\r
3418 \r
3419 \                 $COLON  NameFILL,FILL\r
3420 \                 DW      ROT,ROT,QuestionDUP,ZBranch,FILL2\r
3421 \                 DW      DoLIT,0,DoDO\r
3422 \ FILL1           DW      TwoDUP,CStore,CHARPlus,DoLOOP,FILL1\r
3423 \ FILL2           DW      TwoDROP,EXIT\r
3424 \r
3425 \               $CODE   NameFILL,FILL\r
3426 \               POP     CX\r
3427 \               MOV     DX,SI\r
3428 \               POP     SI\r
3429 \               OR      CX,CX\r
3430 \               JZ      FILL1\r
3431 \               MOV     [SI],BL\r
3432 \               MOV     AX,DS\r
3433 \               MOV     ES,AX\r
3434 \               MOV     DI,SI\r
3435 \               DEC     CX\r
3436 \               INC     DI\r
3437 \               REP MOVSB\r
3438 \ FILL1:                MOV     SI,DX\r
3439 \               POP     BX\r
3440 \               $NEXT\r
3441 \r
3442 \   FIND        ( c-addr -- c-addr 0 | xt 1 | xt -1)     \ SEARCH\r
3443 \               Search dictionary for a match with the given counted name.\r
3444 \               Return execution token and -1 or 1 ( IMMEDIATE) if found;\r
3445 \               c-addr 0 if not found.\r
3446 \r
3447 : FIND          DUP COUNT search-word ?DUP IF NIP ROT DROP EXIT THEN\r
3448                 2DROP 0 ;\r
3449 \r
3450 \               $COLON  NameFIND,FIND\r
3451 \               DW      DUPP,COUNT,Search_word,QuestionDUP,ZBranch,FIND1\r
3452 \               DW      NIP,ROT,DROP,EXIT\r
3453 \ FIND1         DW      TwoDROP,DoLIT,0,EXIT\r
3454 \r
3455 \   IMMEDIATE   ( -- )                          \ CORE\r
3456 \               Make the most recent definition an immediate word.\r
3457 \r
3458 : IMMEDIATE     lastName [ =immed ] LITERAL OVER @ OR SWAP ! ;\r
3459 \r
3460 \               $COLON  NameIMMEDIATE,IMMEDIATE\r
3461 \               DW      LastName,DoLIT,IMMED,OVER,Fetch,ORR,SWAP,Store,EXIT\r
3462 \r
3463 \   J           ( -- n|u ) ( R: loop-sys -- loop-sys )  \ CORE\r
3464 \               Push the index of next outer loop.\r
3465 \r
3466 : J             rp@ [ 3 CELLS ] LITERAL + @\r
3467                 rp@ [ 4 CELLS ] LITERAL + @  +  ; COMPILE-ONLY\r
3468 \r
3469 \                 $COLON  NameJ,J\r
3470 \                 DW      RPFetch,DoLIT,3*CELLL,Plus,Fetch\r
3471 \                 DW      RPFetch,DoLIT,4*CELLL,Plus,Fetch,Plus,EXIT\r
3472 \r
3473 \               $CODE   NameJ,J\r
3474 \               PUSH    BX\r
3475 \               MOV     BX,[BP+2*CELLL]\r
3476 \               ADD     BX,[BP+3*CELLL]\r
3477 \               $NEXT\r
3478 \r
3479 \   LEAVE       ( -- ) ( R: loop-sys -- )       \ CORE\r
3480 \               Terminate definite loop, DO|?DO  ... LOOP|+LOOP, immediately.\r
3481 \r
3482 : LEAVE         POSTPONE UNLOOP POSTPONE branch\r
3483                 xhere rakeVar DUP @ code, ! ; COMPILE-ONLY IMMEDIATE\r
3484 \r
3485 \               $COLON  NameLEAVEE,LEAVEE\r
3486 \               DW      DoLIT,UNLOOP,COMPILEComma,DoLIT,Branch,COMPILEComma\r
3487 \               DW      XHere,DoLIT,AddrRakeVar,DUPP,Fetch,CodeComma,Store,EXIT\r
3488 \r
3489 \   LOOP        Compilation: ( C: do-sys -- )   \ CORE\r
3490 \               Run-time: ( -- ) ( R: loop-sys1 -- loop-sys2 )\r
3491 \               Terminate a DO|?DO ... LOOP structure. Resolve the destination\r
3492 \               of all unresolved occurences of LEAVE.\r
3493 \r
3494 : LOOP          POSTPONE doLOOP  rake ; COMPILE-ONLY IMMEDIATE\r
3495 \r
3496 \               $COLON  NameLOOPP,LOOPP\r
3497 \               DW      DoLIT,DoLOOP,COMPILEComma,rake,EXIT\r
3498 \r
3499 \   LSHIFT      ( x1 u -- x2 )                  \ CORE\r
3500 \               Perform a logical left shift of u bit-places on x1, giving x2.\r
3501 \               Put 0 into the least significant bits vacated by the shift.\r
3502 \r
3503 : LSHIFT        ?DUP IF 0 DO 2* LOOP THEN ;\r
3504 \r
3505 \                 $COLON  NameLSHIFT,LSHIFT\r
3506 \                 DW      QuestionDUP,ZBranch,LSHIFT2\r
3507 \                 DW      DoLIT,0,DoDO\r
3508 \ LSHIFT1         DW      TwoStar,DoLOOP,LSHIFT1\r
3509 \ LSHIFT2         DW      EXIT\r
3510 \r
3511 \               $CODE   NameLSHIFT,LSHIFT\r
3512 \               MOV     CX,BX\r
3513 \               POP     BX\r
3514 \               OR      CX,CX\r
3515 \               JZ      LSHIFT2\r
3516 \               SHL     BX,CL\r
3517 \ LSHIFT2:      $NEXT\r
3518 \r
3519 \   M*          ( n1 n2 -- d )                  \ CORE\r
3520 \               Signed multiply. Return double product.\r
3521 \r
3522 : M*            2DUP XOR 0< >R ABS SWAP ABS UM* R> IF DNEGATE THEN ;\r
3523 \r
3524 \                 $COLON  NameMStar,MStar\r
3525 \                 DW      TwoDUP,XORR,ZeroLess,ToR,ABSS,SWAP,ABSS\r
3526 \                 DW      UMStar,RFrom,ZBranch,MSTAR1\r
3527 \                 DW      DNEGATE\r
3528 \ MSTAR1          DW      EXIT\r
3529 \r
3530 \               $CODE   NameMStar,MStar\r
3531 \               POP     AX\r
3532 \               IMUL    BX\r
3533 \               PUSH    AX\r
3534 \               MOV     BX,DX\r
3535 \               $NEXT\r
3536 \r
3537 \   MAX         ( n1 n2 -- n3 )                 \ CORE\r
3538 \               Return the greater of two top stack items.\r
3539 \r
3540 : MAX           2DUP < IF SWAP THEN DROP ;\r
3541 \r
3542 \                 $COLON  NameMAX,MAX\r
3543 \                 DW      TwoDUP,LessThan,ZBranch,MAX1\r
3544 \                 DW      SWAP\r
3545 \ MAX1            DW      DROP,EXIT\r
3546 \r
3547 \               $CODE   NameMAX,MAX\r
3548 \               POP     AX\r
3549 \               CMP     AX,BX\r
3550 \               JLE     MAX1\r
3551 \               MOV     BX,AX\r
3552 \ MAX1:         $NEXT\r
3553 \r
3554 \   MIN         ( n1 n2 -- n3 )                 \ CORE\r
3555 \               Return the smaller of top two stack items.\r
3556 \r
3557 : MIN           2DUP > IF SWAP THEN DROP ;\r
3558 \r
3559 \                 $COLON  NameMIN,MIN\r
3560 \                 DW      TwoDUP,GreaterThan,ZBranch,MIN1\r
3561 \                 DW      SWAP\r
3562 \ MIN1            DW      DROP,EXIT\r
3563 \r
3564 \               $CODE   NameMIN,MIN\r
3565 \               POP     AX\r
3566 \               CMP     AX,BX\r
3567 \               JGE     MIN1\r
3568 \               MOV     BX,AX\r
3569 \ MIN1:         $NEXT\r
3570 \r
3571 \   MOD         ( n1 n2 -- n3 )                 \ CORE\r
3572 \               Divide n1 by n2, giving the single cell remainder n3.\r
3573 \               Returns modulo of floored division in this implementation.\r
3574 \r
3575 : MOD           /MOD DROP ;\r
3576 \r
3577 \               $COLON  NameMODD,MODD\r
3578 \               DW      SlashMOD,DROP,EXIT\r
3579 \r
3580 \   PICK        ( x_u ... x1 x0 u -- x_u ... x1 x0 x_u )        \ CORE EXT\r
3581 \               Remove u and copy the uth stack item to top of the stack. An\r
3582 \               ambiguous condition exists if there are less than u+2 items\r
3583 \               on the stack before PICK is executed.\r
3584 \r
3585 : PICK          DEPTH DUP 2 < IF -4 THROW THEN    \ stack underflow\r
3586                 2 - OVER U< IF -4 THROW THEN\r
3587                 1+ CELLS sp@ + @ ;\r
3588 \r
3589 \                 $COLON  NamePICK,PICK\r
3590 \                 DW      DEPTH,DUPP,DoLIT,2,LessThan,ZBranch,PICK1\r
3591 \                 DW      DoLIT,-4,THROW\r
3592 \ PICK1           DW      DoLIT,2,Minus,OVER,ULess,ZBranch,PICK2\r
3593 \                 DW      DoLIT,-4,THROW\r
3594 \ PICK2           DW      OnePlus,CELLS,SPFetch,Plus,Fetch,EXIT\r
3595 \r
3596 \               $CODE   NamePICK,PICK\r
3597 \               MOV     DI,AddrUserP\r
3598 \               MOV     DI,[DI+CELLL]   ; sp0\r
3599 \               SUB     DI,SP\r
3600 \               SAR     DI,1            ; depth-1 in DI\r
3601 \               DEC     DI\r
3602 \               JS      PICK1\r
3603 \               CMP     DI,BX\r
3604 \               JB      PICK1\r
3605 \               SHL     BX,1\r
3606 \               ADD     BX,SP\r
3607 \               MOV     BX,[BX]\r
3608 \               $NEXT\r
3609 \ PICK1:                MOV     BX,-4\r
3610 \               JMP     THROW\r
3611 \               $ALIGN\r
3612 \r
3613 \   POSTPONE    ( "<spaces>name" -- )           \ CORE\r
3614 \               Parse name and find it. Append compilation semantics of name\r
3615 \               to current definition.\r
3616 \               Structure of words with special compilation action\r
3617 \                   for default compilation behavior\r
3618 \               |compile_xt|name_ptr| call-doCREATE | 0 or DOES>_xt | a-addr |\r
3619 \r
3620 : POSTPONE      (') 0< IF\r
3621                     specialComp? OVER = IF      \ special compilation action\r
3622                         DUP POSTPONE LITERAL\r
3623                         cell- cell- code@\r
3624                         POSTPONE LITERAL\r
3625                         POSTPONE EXECUTE EXIT  THEN\r
3626                     POSTPONE LITERAL                    \ non-IMMEDIATE\r
3627                     POSTPONE code, EXIT        THEN\r
3628                 code, ; COMPILE-ONLY IMMEDIATE          \ IMMEDIATE\r
3629 \r
3630 \               $COLON  NamePOSTPONE,POSTPONE\r
3631 \               DW      ParenTick,ZeroLess,ZBranch,POSTP1\r
3632 \               DW      SpecialCompQ,OVER,Equals,ZBranch,POSTP2\r
3633 \               DW      DUPP,LITERAL,CellMinus,CellMinus,CodeFetch\r
3634 \               DW      LITERAL,DoLIT,EXECUTE,CodeComma,EXIT\r
3635 \ POSTP2                DW      LITERAL,DoLIT,CodeComma\r
3636 \ POSTP1                DW      CodeComma,EXIT\r
3637 \r
3638 \   RECURSE     ( -- )                          \ CORE\r
3639 \               Append the execution semactics of the current definition to\r
3640 \               the current definition.\r
3641 \r
3642 : RECURSE       bal 1- 2* PICK 1+ IF -22 THROW THEN\r
3643                         \ control structure mismatch; colon-sys type is -1\r
3644                 bal 1- 2* 1+ PICK       \ xt of current definition\r
3645                 COMPILE, ; COMPILE-ONLY IMMEDIATE\r
3646 \r
3647 \               $COLON  NameRECURSE,RECURSE\r
3648 \               DW      Bal,OneMinus,TwoStar,PICK,OnePlus,ZBranch,RECUR1\r
3649 \               DW      DoLIT,-22,THROW\r
3650 \ RECUR1                DW      Bal,OneMinus,TwoStar,OnePlus,PICK\r
3651 \               DW      COMPILEComma,EXIT\r
3652 \r
3653 \   REPEAT      ( C: orig dest -- )             \ CORE\r
3654 \               Terminate a BEGIN-WHILE-REPEAT indefinite loop. Resolve\r
3655 \               backward reference dest and forward reference orig.\r
3656 \r
3657 : REPEAT        POSTPONE AGAIN POSTPONE THEN ; COMPILE-ONLY IMMEDIATE\r
3658 \r
3659 \               $COLON  NameREPEAT,REPEATT\r
3660 \               DW      AGAIN,THENN,EXIT\r
3661 \r
3662 \   RSHIFT      ( x1 u -- x2 )                  \ CORE\r
3663 \               Perform a logical right shift of u bit-places on x1, giving x2.\r
3664 \               Put 0 into the most significant bits vacated by the shift.\r
3665 \r
3666 : RSHIFT        ?DUP IF\r
3667                         0 SWAP  cell-size-in-bits SWAP -\r
3668                         0 DO  2DUP D+  LOOP\r
3669                         NIP\r
3670                 THEN ;\r
3671 \r
3672 \                 $COLON  NameRSHIFT,RSHIFT\r
3673 \                 DW      QuestionDUP,ZBranch,RSHIFT2\r
3674 \                 DW      DoLIT,0,SWAP,DoLIT,CELLL*8,SWAP,Minus,DoLIT,0,DoDO\r
3675 \ RSHIFT1         DW      TwoDUP,DPlus,DoLOOP,RSHIFT1\r
3676 \                 DW      NIP\r
3677 \ RSHIFT2         DW      EXIT\r
3678 \r
3679 \               $CODE   NameRSHIFT,RSHIFT\r
3680 \               MOV     CX,BX\r
3681 \               POP     BX\r
3682 \               OR      CX,CX\r
3683 \               JZ      RSHIFT2\r
3684 \               SHR     BX,CL\r
3685 \ LSHIFT2:      $NEXT\r
3686 \r
3687 \   SLITERAL    ( c-addr1 u -- )                \ STRING\r
3688 \               Run-time ( -- c-addr2 u )\r
3689 \               Compile a string literal. Return the string on execution.\r
3690 \r
3691 : SLITERAL      ALIGN HERE POSTPONE LITERAL DUP POSTPONE LITERAL\r
3692                 CHARS HERE  2DUP + ALIGNED TO HERE\r
3693                 SWAP MOVE ; COMPILE-ONLY IMMEDIATE\r
3694 \r
3695 \               $COLON  NameSLITERAL,SLITERAL\r
3696 \               DW      ALIGNN,HERE,LITERAL,DUPP,LITERAL\r
3697 \               DW      CHARS,HERE,TwoDUP,Plus,ALIGNED,DoTO,AddrHERE\r
3698 \               DW      SWAP,MOVE,EXIT\r
3699 \r
3700 \   S"          Compilation: ( "ccc<">" -- )    \ CORE\r
3701 \               Run-time: ( -- c-addr u )\r
3702 \               Parse ccc delimetered by " . Return the string specification\r
3703 \               c-addr u on execution.\r
3704 \r
3705 : S"            [CHAR] " PARSE POSTPONE SLITERAL ; COMPILE-ONLY IMMEDIATE\r
3706 \r
3707 \               $COLON  NameSQuote,SQuote\r
3708 \               DW      DoLIT,'"',PARSE,SLITERAL,EXIT\r
3709 \r
3710 \   SM/REM      ( d n1 -- n2 n3 )               \ CORE\r
3711 \               Symmetric divide of double by single. Return remainder n2\r
3712 \               and quotient n3.\r
3713 \r
3714 : SM/REM        OVER >R >R DUP 0< IF DNEGATE THEN\r
3715                 R@ ABS UM/MOD DUP 0<\r
3716                 IF DUP [ 16 BASE ! ] 8000 [ DECIMAL ] XOR IF -11 THROW THEN THEN \ result out of range\r
3717                 R> R@ XOR 0< IF NEGATE THEN\r
3718                 R> 0< IF SWAP NEGATE SWAP THEN ;\r
3719 \r
3720 \                 $COLON  6,'SM/REM',SMSlashREM,_FLINK\r
3721 \                 DW      OVER,ToR,ToR,DUPP,ZeroLess,ZBranch,SMREM1\r
3722 \                 DW      DNEGATE\r
3723 \ SMREM1          DW      RFetch,ABSS,UMSlashMOD,DUPP,ZeroLess,ZBranch,SMREM4\r
3724 \                 DW      DUPP,DoLIT,08000h,XORR,ZBranch,SMREM4\r
3725 \                 DW      DoLIT,-11,THROW\r
3726 \ SMREM4          DW      RFrom,RFetch,XORR,ZeroLess,ZBranch,SMREM2\r
3727 \                 DW      NEGATE\r
3728 \ SMREM2          DW      RFrom,ZeroLess,ZBranch,SMREM3\r
3729 \                 DW      SWAP,NEGATE,SWAP\r
3730 \ SMREM3          DW      EXIT\r
3731 \r
3732 \               $CODE   NameSMSlashREM,SMSlashREM\r
3733 \               POP     DX\r
3734 \               POP     AX\r
3735 \               OR      DX,DX\r
3736 \               JS      SMREM2\r
3737 \               OR      BX,BX\r
3738 \               JZ      SMREM1\r
3739 \               JS      SMREM3\r
3740 \               CMP     DX,BX\r
3741 \               JAE     SMREM6\r
3742 \               DIV     BX              ;positive dividend, positive divisor\r
3743 \               CMP     AX,08000h\r
3744 \               JA      SMREM6\r
3745 \               PUSH    DX\r
3746 \               MOV     BX,AX\r
3747 \               $NEXT\r
3748 \ SMREM3:       NEG     BX              ;positive dividend, negative divisor\r
3749 \               CMP     DX,BX\r
3750 \               JAE     SMREM6\r
3751 \               DIV     BX\r
3752 \               CMP     AX,08000h\r
3753 \               JA      SMREM6\r
3754 \               MOV     BX,AX\r
3755 \               PUSH    DX\r
3756 \               NEG     BX\r
3757 \               $NEXT\r
3758 \ SMREM2:       NEG     AX              ;DNEGATE\r
3759 \               ADC     DX,0\r
3760 \               NEG     DX\r
3761 \               OR      BX,BX\r
3762 \               JZ      SMREM1\r
3763 \               JS      SMREM4\r
3764 \               CMP     DX,BX           ;negative dividend, positive divisor\r
3765 \               JAE     SMREM6\r
3766 \               DIV     BX\r
3767 \               CMP     AX,08000h\r
3768 \               JA      SMREM6\r
3769 \               NEG     DX\r
3770 \               MOV     BX,AX\r
3771 \               PUSH    DX\r
3772 \               NEG     BX\r
3773 \               $NEXT\r
3774 \ SMREM4:       NEG     BX              ;negative dividend, negative divisor\r
3775 \               CMP     DX,BX\r
3776 \               JAE     SMREM6\r
3777 \               DIV     BX\r
3778 \               CMP     AX,08000h\r
3779 \               JA      SMREM6\r
3780 \               NEG     DX\r
3781 \               MOV     BX,AX\r
3782 \               PUSH    DX\r
3783 \               $NEXT\r
3784 \ SMREM6:       MOV     BX,-11          ;result out of range\r
3785 \               JMP     THROW\r
3786 \ SMREM1:       MOV     BX,-10          ;divide by zero\r
3787 \               JMP     THROW\r
3788 \               $ALIGN\r
3789 \r
3790 \   SPACES      ( n -- )                        \ CORE\r
3791 \               Send n spaces to the output device if n is greater than zero.\r
3792 \r
3793 : SPACES        DUP 0 > IF 0 DO SPACE LOOP EXIT THEN DROP ;\r
3794 \r
3795 \                 $COLON  6,'SPACES',SPACES,_FLINK\r
3796 \                 DW      DUPP,Zero,GreaterThan,ZBranch,SPACES1\r
3797 \                 DW      Zero,DoDO\r
3798 \ SPACES2         DW      SPACE,DoLOOP,SPACES2\r
3799 \                 DW      EXIT\r
3800 \ SPACES1         DW      DROP,EXIT\r
3801 \r
3802 \               $CODE   NameSPACES,SPACES\r
3803 \               OR      BX,BX\r
3804 \               JLE     SPACES2\r
3805 \               PUSH    SI\r
3806 \               SUB     BP,CELLL\r
3807 \               MOV     [BP],BX\r
3808 \               MOV     BX,' '\r
3809 \ SPACES4:      PUSH    BX\r
3810 \               MOV     SI,OFFSET SPACES3\r
3811 \               MOV     AX,AddrTickEMIT\r
3812 \               JMP     AX\r
3813 \ SPACES1:      DEC     WORD PTR [BP]\r
3814 \               JNZ     SPACES4\r
3815 \               POP     SI\r
3816 \               ADD     BP,CELLL\r
3817 \ SPACES2:      POP     BX\r
3818 \               $NEXT\r
3819 \ SPACES3       DW      SPACES1\r
3820 \r
3821 \   TO          Interpretation: ( x "<spaces>name" -- ) \ CORE EXT\r
3822 \               Compilation:    ( "<spaces>name" -- )\r
3823 \               Run-time:       ( x -- )\r
3824 \               Store x in name.\r
3825 \r
3826 : TO            ' ?call ?DUP IF         \ should be CALL\r
3827                   ['] doVALUE =         \ verify VALUE marker\r
3828                   IF code@ STATE @\r
3829                      IF POSTPONE doTO code, EXIT THEN\r
3830                      ! EXIT\r
3831                      THEN THEN\r
3832                 -32 THROW ; IMMEDIATE   \ invalid name argument (e.g. TO xxx)\r
3833 \r
3834 \               $COLON  NameTO,TO\r
3835 \               DW      Tick,QCall,QuestionDUP,ZBranch,TO1\r
3836 \               DW      DoLIT,DoVALUE,Equals,ZBranch,TO1\r
3837 \               DW      CodeFetch,DoLIT,AddrSTATE,Fetch,ZBranch,TO2\r
3838 \               DW      DoLIT,DoTO,COMPILEComma,CodeComma,EXIT\r
3839 \ TO2           DW      Store,EXIT\r
3840 \ TO1           DW      DoLIT,-32,THROW\r
3841 \r
3842 \   U.          ( u -- )                        \ CORE\r
3843 \               Display u in free field format followed by space.\r
3844 \r
3845 : U.            0 D. ;\r
3846 \r
3847 \               $COLON  NameUDot,UDot\r
3848 \               DW      DoLIT,0,DDot,EXIT\r
3849 \r
3850 \   UNTIL       ( C: dest -- )                  \ CORE\r
3851 \               Terminate a BEGIN-UNTIL indefinite loop structure.\r
3852 \r
3853 : UNTIL         IF -22 THROW THEN  \ control structure mismatch; dest type is 0\r
3854                 POSTPONE 0branch code, bal- ; COMPILE-ONLY IMMEDIATE\r
3855 \r
3856 \               $COLON  NameUNTIL,UNTIL\r
3857 \               DW      ZBranch,UNTIL1\r
3858 \               DW      DoLIT,-22,THROW\r
3859 \ UNTIL1                DW      DoLIT,ZBranch,COMPILEComma,CodeComma,BalMinus,EXIT\r
3860 \r
3861 \   VALUE       ( x "<spaces>name" -- )         \ CORE EXT\r
3862 \               name Execution: ( -- x )\r
3863 \               Create a value object with initial value x.\r
3864 \r
3865 : VALUE         bal IF -29 THROW THEN           \ compiler nesting\r
3866                 xhere ALIGNED CELL+ TO xhere\r
3867                 ['] doVALUE xt, head,\r
3868                 ALIGN HERE code,\r
3869                 , linkLast ; \ store x and link CREATEd word to current wordlist\r
3870 \r
3871 \               $COLON  NameVALUE,VALUE\r
3872 \               DW      Bal,ZBranch,VALUE1\r
3873 \               DW      DoLIT,-29,THROW\r
3874 \ VALUE1                DW      XHere,ALIGNED,CELLPlus,DoTO,AddrXHere\r
3875 \               DW      DoLIT,DoVALUE,xtComma,HeadComma\r
3876 \               DW      ALIGNN,HERE,CodeComma\r
3877 \               DW      Comma,LinkLast,EXIT\r
3878 \r
3879 \   VARIABLE    ( "<spaces>name" -- )           \ CORE\r
3880 \               name Execution: ( -- a-addr )\r
3881 \               Parse a name and create a variable with the name.\r
3882 \               Resolve one cell of data space at an aligned address.\r
3883 \               Return the address on execution.\r
3884 \r
3885 : VARIABLE      bal IF -29 THROW THEN           \ compiler nesting\r
3886                 xhere ALIGNED TO xhere\r
3887                 ['] compileCONST code,\r
3888                 xhere CELL+ TO xhere\r
3889                 ['] doCONST xt, head,\r
3890                 ALIGN HERE\r
3891                 1 CELLS ALLOT           \ allocate one cell in data space\r
3892                 code, linkLast\r
3893                 lastName [ =seman ] LITERAL OVER @ OR SWAP ! ;\r
3894 \r
3895 \               $COLON  NameVARIABLE,VARIABLE\r
3896 \               DW      Bal,ZBranch,VARIA1\r
3897 \               DW      DoLIT,-29,THROW\r
3898 \ VARIA1                DW      XHere,ALIGNED,DoTO,AddrXHere\r
3899 \               DW      DoLIT,CompileCONST,CodeComma\r
3900 \               DW      XHere,CELLPlus,DoTO,AddrXHere\r
3901 \               DW      DoLIT,DoCONST,xtComma,HeadComma\r
3902 \               DW      ALIGNN,HERE,DoLIT,1*CELLL,ALLOT\r
3903 \               DW      CodeComma,LinkLast\r
3904 \               DW      LastName,DoLIT,SEMAN,OVER,Fetch,ORR,SWAP,Store,EXIT\r
3905 \r
3906 \   WHILE       ( C: dest -- orig dest )        \ CORE\r
3907 \               Put the location of a new unresolved forward reference orig\r
3908 \               onto the control flow stack under the existing dest. Typically\r
3909 \               used in BEGIN ... WHILE ... REPEAT structure.\r
3910 \r
3911 : WHILE         POSTPONE IF 2SWAP ; COMPILE-ONLY IMMEDIATE\r
3912 \r
3913 \               $COLON  NameWHILE,WHILEE\r
3914 \               DW      IFF,TwoSWAP,EXIT\r
3915 \r
3916 \   WORD        ( char "<chars>ccc<char>" -- c-addr )   \ CORE\r
3917 \               Skip leading delimeters and parse a word. Return the address\r
3918 \               of a transient region containing the word as counted string.\r
3919 \r
3920 : WORD          skipPARSE HERE pack" DROP HERE ;\r
3921 \r
3922 \               $COLON  NameWORDD,WORDD\r
3923 \               DW      SkipPARSE,HERE,PackQuote,DROP,HERE,EXIT\r
3924 \r
3925 \   [']         Compilation: ( "<spaces>name" -- )      \ CORE\r
3926 \               Run-time: ( -- xt )\r
3927 \               Parse name. Return the execution token of name on execution.\r
3928 \r
3929 : [']           ' POSTPONE LITERAL ; COMPILE-ONLY IMMEDIATE\r
3930 \r
3931 \               $COLON  NameBracketTick,BracketTick\r
3932 \               DW      Tick,LITERAL,EXIT\r
3933 \r
3934 \   [CHAR]      Compilation: ( "<spaces>name" -- )      \ CORE\r
3935 \               Run-time: ( -- char )\r
3936 \               Parse name. Return the value of the first character of name\r
3937 \               on execution.\r
3938 \r
3939 : [CHAR]        CHAR POSTPONE LITERAL ; COMPILE-ONLY IMMEDIATE\r
3940 \r
3941 \               $COLON  NameBracketCHAR,BracketCHAR\r
3942 \               DW      CHAR,LITERAL,EXIT\r
3943 \r
3944 \   \           ( "ccc<eol>" -- )               \ CORE EXT\r
3945 \               Parse and discard the remainder of the parse area.\r
3946 \r
3947 : \             SOURCE >IN ! DROP ; IMMEDIATE\r
3948 \r
3949 \               $COLON  NameBackslash,Backslash\r
3950 \               DW      SOURCE,DoLIT,AddrToIN,Store,DROP,EXIT\r
3951 \r
3952 \ Optional Facility words\r
3953 \r
3954 \   EKEY?       ( -- flag )                     \ FACILITY EXT\r
3955 \               If a keyboard event is available, return true.\r
3956 \r
3957 : EKEY?         'ekey? EXECUTE ;\r
3958 \r
3959 \                 $COLON  NameEKEYQuestion,EKEYQuestion\r
3960 \                 DW      TickEKEYQ,EXECUTE,EXIT\r
3961 \r
3962 \               $CODE   NameEKEYQuestion,EKEYQuestion\r
3963 \               MOV     AX,AddrTickEKEYQ\r
3964 \               JMP     AX\r
3965 \               $ALIGN\r
3966 \r
3967 \   EMIT?       ( -- flag )                     \ FACILITY EXT\r
3968 \               flag is true if the user output device is ready to accept data\r
3969 \               and the execution of EMIT in place of EMIT? would not have\r
3970 \               suffered an indefinite delay. If device state is indeterminate,\r
3971 \               flag is true.\r
3972 \r
3973 : EMIT?         'emit? EXECUTE ;\r
3974 \r
3975 \                 $COLON  NameEMITQuestion,EMITQuestion\r
3976 \                 DW      TickEMITQ,EXECUTE,EXIT\r
3977 \r
3978 \               $CODE   NameEMITQuestion,EMITQuestion\r
3979 \               MOV     AX,AddrTickEMITQ\r
3980 \               JMP     AX\r
3981 \               $ALIGN\r
3982 \r
3983 \ Nick\r
3984 \ ' RX? TO 'ekey?\r
3985 \ ' RX@ TO 'ekey\r
3986 \ ' TX? TO 'emit?\r
3987 \ ' TX! TO 'emit\r
3988 ' set-i/o TO 'init-i/o\r
3989 ' .ok TO 'prompt\r
3990 ' hi TO 'boot\r
3991 ' optiCOMPILE, 'doWord !\r
3992 \ ' EXECUTE 'doWord 2 + !\r
3993 ' doubleAlso, 'doWord 4 + !\r
3994 ' doubleAlso 'doWord 6 + !\r
3995 \ ' EXECUTE 'doWord 8 + !\r
3996 \ ' EXECUTE 'doWord 10 + !\r
3997 \r
3998 << CON\r