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