1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; word finder utilities
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10 ;; hash table (if there is any)
12 $IF !DSFORTH_TURNKEY || (defined(DSFORTH_KEEP_HEADERS) && DSFORTH_KEEP_HEADERS)
14 $FORTH_DOES_CODE FORTH voc_does_code IMM
15 $ENDIF ;; !DSFORTH_TURNKEY
24 ;; CONTEXT and CURRENT points here
32 forth_hash_table_offset equ forth_hash_tbl-forth_voc_latest
33 ;;$printf "forth_hash_table_offset=%s", forth_hash_table_offset
35 $IF !DSFORTH_TURNKEY || (defined(DSFORTH_KEEP_HEADERS) && DSFORTH_KEEP_HEADERS)
37 $ENDIF ;; !DSFORTH_TURNKEY
42 include "main_wfind_hashed.zas"
44 include "main_wfind_linear.zas"
49 ; ENCLOSE ( addr1 c -- addr1 w_start_ofs w_end_ofs next_scan_ofs )
50 ; The text scanning primitive used by WORD.
51 ; From the text address addr1 and an ascii delimiting character c,
53 ; `w_start_ofs`: the byte offset to the first non-delimiter character
54 ; `w_end_ofs`: the offset to the first delimiter after the text
55 ; `next_scan_ofs`: the offset to the first character not included
56 ; Note that `addr1` will be returned unmodified.
57 ; This procedure will not process past an ascii "null", treating it
58 ; as an unconditional delimiter.
59 $FORTH_CODE_WORD ENCLOSE NOTURNKEY
61 ;; ( addr delimeter -- addr w_start_ofs w_end_ofs next_scan_ofs )
71 ; here: E=word len; A=delim; HL=addr
80 push de ; store # of delimiters before the word
83 ; check for "end of buffer" (#0)
88 ; oops... no more blondies
91 push de ; store full length
94 push de ; store position of the next char to scan
97 ; here: E=word len; D=delim; HL=addr
99 ; now collect the word itself
104 jr z,enclose2 ; word ends?
105 ; no, check "end of buffer"
110 ; oops... no more blondies on the island
112 push de ; store full length
113 push de ; store position of the next char to scan (???)
118 push de ; store full length
120 push de ; store position of the next char to scan
122 $FORTH_END_CODE_WORD ENCLOSE
126 $FORTH_WORD (FIND-COMPLETION) NOTURNKEY
127 ;; ( addr count latest 0 -- addr count oknfa-or-0 )
128 ;; ( addr count nfa-to-skip 1 -- addr count oknfa-or-0 )
129 ;;DUMP-STACK KEY DROP
134 ;; ( addr count lfa )
137 ;; ( addr count nfa )
139 ;; ( addr count nfa )
140 ;;CR >R 2DUP XTYPE [CHAR] | XEMIT R@ ID. R>
141 2DUP C@ LIT 31 AND > TBRANCH .badlen
142 ;; ( addr count nfa )
143 ;;SPACE DUP ID. KEY DROP CR
144 >R 2DUP R@ 1+ NROT ;; ( addr count nfa addr count | nfa )
146 ;; ( addr count cmpflag | nfa )
148 ;;DUMP-STACK KEY DROP
149 ;; ( addr count nfa cmpflag )
152 ;; ( addr count nfa )
153 ;;DUMP-STACK KEY DROP
159 $FORTH_END_WORD (FIND-COMPLETION)
163 $FORTH_CODE_WORD (FIND-COMPLETION) NOTURNKEY
164 ;; ( addr count latest 0 -- addr count oknfa-or-0 )
165 ;; ( addr count nfa-to-skip 1 -- addr count oknfa-or-0 )
166 fword_find_completion:
170 ; now prepare everything for the loop
172 ld (fwcompl_curr_lfa),hl
187 jr z,fwcompl_len_fucked
189 jr nc,fwcompl_len_fucked
190 ; source word length is ok, write vars
191 ld (fwcompl_straddr),de
192 ld (fwcompl_strlen_cmp),a
193 ld (fwcompl_strlen_cnt),a
194 ; get back our flag (and BC)
199 ld hl,(fwcompl_curr_lfa)
200 ; check for zero address
203 jr z,fwcompl_end_of_list
204 ; DE is NFA, move do next word
205 jr fwcompl_next_word_hl
209 ; move to the next lfa
211 fwcompl_curr_lfa equ $-2
216 ld (fwcompl_curr_nfa),hl
219 jr z,fwcompl_end_of_list
224 cp 0 ; patched in the setup code
225 fwcompl_strlen_cmp equ $-1
226 jr c,fwcompl_next_word ; too long
227 ; length is ok, compare strings
228 ld de,0 ; patched in the setup code
229 fwcompl_straddr equ $-2
230 ld a,0 ; patched in the setup code
231 fwcompl_strlen_cnt equ $-1
239 jr nz,fwcompl_next_word
244 jr nz,fwcompl_scmp_loop
245 ; equal, return this word
246 ld hl,(fwcompl_straddr)
248 ld hl,(fwcompl_strlen_cmp)
251 ld hl,(fwcompl_curr_nfa)
255 fwcompl_curr_nfa equ $-2
256 fwcompl_next_word_hl:
263 ld (fwcompl_curr_lfa),hl
266 ld hl,(fwcompl_straddr)
268 ld hl,(fwcompl_strlen_cmp)
274 $FORTH_END_CODE_WORD (FIND-COMPLETION)
282 CONTEXT @ 0 (FIND-COMPLETION)
301 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
302 ;; create word header and vocabulary
303 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
305 ; A defining word used in the form: CREATE cccc
306 ; by such words as CODE and CONSTANT to create a dictionary header for
307 ; a Forth definition. The code field contains the routine that returnrn
308 ; the address of the word's parameter field. The new word is created in
309 ; the current vocabulary.
310 ; Note that SMUDGE bit is set (i.e. the word is invisible).
311 $FORTH_WORD CREATE NOTURNKEY
315 ;; put 0 for hashtable link
316 HERE >R ;; save BFA to rstack
319 ;; check for duplicate word
320 ;; k8: look only in the current dictionary
322 ;; check for word redefinition?
323 REDEFCHK @ 0BRANCH create1
324 CURRENT @ (XFIND) 0BRANCH create0
325 ;; found duplicate, tell the user about it
326 ;; (XFIND) already returned name length for us, so use it
327 LIT 31 AND - 3- ;; 3- moves from CFA to the last name byte
328 ENDCR ID. 4 MESSAGE ENDCR ;;SPACE
330 ;; counted word name is at HERE
333 DUP C@ ;; ( orig-HERE count )
334 LIT 31 MIN ;; was `WIDTH @` instead of `LIT 31` ( orig-HERE count )
335 1+ ALLOT ;; ( orig-HERE )
336 DUP LIT #A0 TOGGLE ;; set SMUDGE and BIT7 ( orig-HERE )
338 HERE 1- LIT #80 TOGGLE ;; toggle BIT7 in the last name byte
342 ;; the stack is empty here
343 ;; save orig-HERE to vocabulary LFAPTR
347 LIT _dovar , ;; to _dovar
350 R@ 2+ (XHASHNAME) 2U* ;; ( hash*2 | bfa )
351 CURRENT @ (VOC-WLINK->HTBL) + ;; ( htaddr | bfa )
352 ;; set [bfa] to [htaddr]
353 DUP @ R@ ! ;; ( htaddr | bfa )
354 ;; set [htaddr] to bfa
358 $FORTH_END_WORD CREATE
361 $FORTH_WORD VOCABULARY NOTURNKEY
364 ;; $IF !DSFORTH_TURNKEY
375 0 , ;; new vocabulary doesn't inherit the old one
378 ;;NOTUSED;; HERE VOC-LINK @ ,
379 ;;NOTUSED;; VOC-LINK !
386 ;; $ENDIF ;; !DSFORTH_TURNKEY
388 ;; skip over dummy word name
396 $FORTH_END_WORD VOCABULARY
410 $FORTH_WORD FORGET NOTURNKEY
413 CURRENT @ CONTEXT @ - LIT 24 ?ERROR
414 ' DUP FENCE @ U< LIT 21 ?ERROR
415 DUP CFA->NFA DP ! CFA->LFA @ CURRENT @ !
417 ;;FIXME: trace and remove instead of rehashing?
418 CONTEXT @ (VOC-REHASH)
421 $FORTH_END_WORD FORGET