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