home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / f / forthmac / !Forthmacs / lib / block < prev    next >
Encoding:
Text File  |  1997-04-17  |  4.9 KB  |  162 lines

  1. \ < This file implements standard Forth BLOCKs
  2. \ The buffer management scheme is based on an LRU (Least Recently Used)
  3. \ replacement policy.  This implementation was adapted from the buffer
  4. \ > management code in F83; thanks to Mike Perry and Henry Laxen.
  5.  
  6. decimal
  7.  
  8. nuser scr
  9. nuser blk
  10. nuser offset    0 offset !    \ Used to bias block numbers
  11. nuser block-fid    0 block-fid !    \ 0 for global blocks, fileid for blocks in files
  12. : >in    ( -- adr )    bfcurrent  ;
  13. \needs d=    : d=    ( d1 d2 -- f )    rot = -rot = and  ;
  14.  
  15. \ Interfaces to the system-dependent code that does the actual I/O
  16.  
  17. defer read-block    (s adr block# fileid -- )
  18. defer write-block    (s adr block# fileid -- )
  19.  
  20. 1024 constant b/buf
  21.   64 constant c/l
  22.  
  23. \ The order of >block# and >file# must be preserved, and they
  24. \ must be at the start of the structure.  The program accesses
  25. \ them both at once with    <header-address> 2@
  26.  
  27. struct ( buffer-header )
  28.  /cell field >file#
  29.  /cell field >block#
  30.  /cell field >bufadd
  31.  /cell field >bufflags    \ -1 dirty block  0 clean block  1 no block
  32. constant /bufhdr
  33.  
  34. : /bufhdr*    ( u1 -- u2 )    /bufhdr * ;
  35.  
  36. \ < Some debugging tools
  37. \ : .bh    ( buffer-header -- )
  38. \    dup >block#    " Block# "    @ .
  39. \    dup >file#    ."   File# "    @ .
  40. \    dup >bufadd    ."   Address "    @ .
  41. \    >bufflags    ."   Flags "    @ . ;
  42. \ : .bhs    (s -- )    #buffers 1+ 0  do  i >header .bh  cr  loop  ;
  43. \ : .read    ( bufadd file block -- )    ." Read "  . . . cr ;
  44. \ : .write    ( bufadd file block -- )    ." Write " . . . cr ;
  45. \  ' .read  is read-block
  46. \  ' .write is write-block
  47.  
  48. \ > Allocation of data structures
  49.  
  50. 4 value #buffers
  51.  
  52. #buffers 1+ /bufhdr*  buffer: bufhdrs
  53. b/buf #buffers *      buffer: first
  54.  
  55. : >header    (s n -- adr )    /bufhdr* bufhdrs +   ;
  56. : >update    (s -- adr )    1 >header >bufflags  ;
  57. : update    (s -- )        >update on   ;
  58. : discard    (s -- )        1 >update !  ;
  59.  
  60. \ Write buffer if it is dirty
  61. : ?write-block    ( buf-header -- buf-header )
  62.     dup >bufflags @ 0<
  63.     if    dup >bufadd @ over 2@ write-block
  64.         dup >bufflags off
  65.     then ;
  66.  
  67. \ Discard least-recently-used buffer, writing it if necessary,
  68. \ and move it to the head of the list.
  69. : replace-buffer    (s -- )
  70.     #buffers >header  ?write-block            ( last-buffer-header )
  71.     >bufadd @  bufhdrs >bufadd !            ( ) \ Copy buffer address
  72.     bufhdrs dup /bufhdr + #buffers /bufhdr*  move    ( ) \ Move into position
  73.     discard ;                        \ No assigned block
  74.  
  75. : file-buffer    (s u fileid -- adr )
  76.     pause
  77.     \ Quick check in case the first buffer in the cache is the one we want
  78.     swap  offset @ +  swap            ( u' fileid )
  79.     2dup   1 >header 2@  d= 0=
  80.     if    \ Search the buffer cache    ( u fileid )
  81.         true #buffers 1+ 2
  82.         do    drop  2dup i >header 2@ d=
  83.            if    ( u fileid )
  84.             \ Found it; move it to the head of the list
  85.             i >header        ( u fileid &hdrN)
  86.             dup bufhdrs /bufhdr move    ( u fileid &hdrN )
  87.             >r  bufhdrs dup /bufhdr +    ( u fileid &hdr0 &hdr1 )
  88.             over r> swap  -  move        ( u fileid )
  89.             false leave            ( u fileid false )
  90.            then                    ( u fileid )
  91.            true
  92.         loop                    ( u fileid not-in-cache? )
  93.         if 2dup bufhdrs 2!  replace-buffer then    ( u fileid )
  94.     then    ( u fileid )
  95.     2drop  1 >header >bufadd @ ;            ( buffer-adr )
  96.  
  97. : file-block    (s u fileid -- a )
  98.     file-buffer  >update @ 0>
  99.     if            \ Contents invalid?
  100.         1 >header  dup >bufadd @    ( adr hdr buf )
  101.         swap 2@  read-block        ( adr )    \ Read it in
  102.         >update off            ( adr )
  103.     then ;
  104.  
  105. : empty-buffers    (s -- )
  106.     first    b/buf #buffers *      erase    \ Clear buffers
  107.     bufhdrs  #buffers 1+ /bufhdr*  erase    \ Clear headers
  108.     first                    ( adr )
  109.     1 >header  #buffers /bufhdr*  bounds
  110.     do    -1  i >block# !            ( adr )    \ Invalid block#
  111.         dup i >bufadd !            ( adr )    \ Point to buffer
  112.         b/buf +                ( adr' )
  113.     /bufhdr +loop  drop ;
  114.  
  115. : save-buffers    (s -- )
  116.     1 >header  #buffers /bufhdr*  bounds
  117.     do    i >block# @  -1 <>
  118.         if i ?write-block drop then
  119.     /bufhdr +loop ;
  120.  
  121. : buffer    (s n -- a )    block-fid @ file-buffer  ;
  122. : block        (s n -- a )    block-fid @ file-block   ;
  123. : flush        (s -- )        save-buffers  0 block drop  empty-buffers  ;
  124. : block-sizeop    (s fid -- n )    drop b/buf  ;
  125. : load-file    (s block# fileid -- )
  126.     blk @ >r  over blk !  ( block# fileid )
  127.     file-block
  128.     get-fd
  129.     bfbase @  b/buf  move            \ Copy in buffer contents
  130.     bfbase @  b/buf +  dup bftop !  bfend !    \ Set limit pointers
  131.     0 modify                \ Low-level stream operations
  132.     ['] block-sizeop  ['] noop       ['] drop
  133.     ['] nullseek      ['] fakewrite  ['] nullread
  134.     setupfd
  135.     file @ (fload)
  136.     r> blk ! ;
  137. : load    ( block# -- )    block-fid @ load-file  ;
  138.  
  139. \ Backslash (comment to end of line) for blocks
  140. : \    \ rest-of-line  ( -- )
  141.     input-file @ file !
  142.     sizeop @  ['] block-sizeop  =
  143.     if    bfcurrent @  bfbase @ -
  144.         c/l 1- +   c/l 1- not  and
  145.         bfbase @ +  bflimit @  umin  bfcurrent !
  146.     else    postpone \
  147.     then ; immediate
  148.  
  149. : thru    (s n1 n2 -- )    2 ?enough   1+ swap ?do   i load   loop   ;
  150. : +thru    (s n1 n2 -- )    blk @ + swap   blk @ + swap   thru   ;
  151. : -->    (s -- )        input-file @ fclose  blk @ 1+ load  ;   immediate
  152. : list    (s scr# -- )
  153.     dup scr !  ." Screen " dup .  cr  ( scr# )
  154.     block  b/buf  bounds
  155.     do   i  c/l  type  cr  c/l +loop ;
  156. : n    (s -- )        1 scr +!  ;
  157. : b    (s -- )        -1 scr +!  ;
  158. : l    (s -- )        scr @ list  ;
  159.  
  160. empty-buffers
  161.