\ @(#) filefind.fth 98/01/26 1.2
\ FILE?  ( <name> -- , report which file this Forth word was defined in )
\
\ FILE? looks for ::::Filename and ;;;; in the dictionary
\ that have been left by INCLUDE.  It figures out nested
\ includes and reports each file that defines the word.
\
\ Author: Phil Burk
\ Copyright 1992 Phil Burk
\
\ 00001 PLB 2/21/92 Handle words from kernel or keyboard.
\       Support EACH.FILE?
\ 961213 PLB Port to pForth.

ANEW TASK-FILEFIND.FTH

: BE@ { addr | val -- val , fetch from unaligned address in BigEndian order }
    4 0
    DO
        addr i + c@
        val 8 lshift or -> val
    LOOP
    val
;

: BE! { val addr -- , store to unaligned address in BigEndian order }
    4 0
    DO
        val 3 i - 8 * rshift
        addr i + c!
    LOOP
;
: BEW@ { addr -- , fetch word from unaligned address in BigEndian order }
    addr c@ 8 lshift
    addr 1+ c@ OR
;

: BEW! { val addr -- , store word to unaligned address in BigEndian order }
    val 8 rshift addr c!
    val addr 1+ c!
;

\ scan dictionary from NFA for filename
: F?.SEARCH.NFA { nfa | dpth stoploop keyb nfa0 -- addr count }
    0 -> dpth
    0 -> stoploop
    0 -> keyb
    nfa -> nfa0
    BEGIN
        nfa prevname -> nfa
        nfa 0>
        IF
            nfa 1+ be@
            CASE
                $ 3a3a3a3a ( :::: )
                OF
                    dpth 0=
                    IF
                        nfa count 31 and
                        4 - swap 4 + swap
                        true -> stoploop
                    ELSE
                        -1 dpth + -> dpth
                    THEN
                ENDOF
                $ 3b3b3b3b ( ;;;; )
                OF
                        1 dpth + -> dpth
                        true -> keyb     \ maybe from keyboard
                ENDOF
            ENDCASE
        ELSE
            true -> stoploop
            keyb
            IF
                " keyboard"
            ELSE
                " 'C' kernel"
            THEN
            count
        THEN
        stoploop
    UNTIL
;

: FINDNFA.FROM { $name start_nfa -- nfa true | $word false }
    context @ >r
    start_nfa context !
    $name findnfa
    r> context !
;

\ Search entire dictionary for all occurences of named word.
: FILE? {  | $word nfa done? -- , take name from input }
    0 -> done?
    bl word -> $word
    $word findnfa
    IF  ( -- nfa )
        $word count type ."  from:" cr
        -> nfa
        BEGIN
            nfa f?.search.nfa ( addr cnt )
            nfa name> 12 .r   \ print xt
            4 spaces type cr
            nfa prevname dup -> nfa
            0>
            IF
                $word nfa findnfa.from  \ search from one behind found nfa
                swap -> nfa
                not
            ELSE
                true
            THEN
        UNTIL
    ELSE ( -- $word )
        count type ."  not found!" cr
    THEN
;

