home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / language / f68k.zoo / docf68k.txt < prev    next >
Text File  |  1992-02-01  |  142KB  |  4,623 lines

  1. Far from being complete, but it is a beginning ...
  2.  
  3.  
  4. /**************************************************************\
  5. *                                                              *
  6. *                        F68K                                  *
  7. *                                                              *
  8. *                                                              *
  9. *             Technical Reference Manual                       *
  10. *                                                              *
  11. *                                                              *
  12. * last change: 06-24-91                                        *
  13. \**************************************************************/
  14.  
  15.  
  16. Content
  17.  
  18.      F68K copyright notes
  19.      Introduction
  20.      Forth-83?
  21.      Loader
  22.      Input and output
  23.      Mass storage
  24.      Pointer and addresses
  25.      Header
  26.      USER variables
  27.      Values and locals
  28.      Vocabularies
  29.      Interpreter
  30.      Control structures
  31.      Reducing the kernel
  32.      F68K streaminterface
  33.      Lineeditor
  34.      Fullscreen editor (not longer provided)
  35.      F-EDIT
  36.      Possible errors
  37.  
  38.      Documenation of loader implementations
  39.         Atari ST
  40.         Sinclair QL
  41.         Commodore Amiga
  42.  
  43.      Glossary
  44.  
  45.  
  46. ###############################################################
  47. F68K COPYRIGHT NOTES
  48. ###############################################################
  49.  
  50.  
  51.  
  52. F68K   was   created   to  support  distribution  of  the  FORTH
  53. programmimg  language.  So there are only shareware-fees on F68K
  54. for  PRIVATE use. You are free to make, use and give away copies
  55. of  F68K,  as  long  as the author's names are left visible, and
  56. this file comes to the new user, too.
  57.  
  58.  
  59. ****************************************************************
  60. Important!!!
  61. ****************************************************************
  62.  
  63. F68K will never be ready. It shall develop continously. So there
  64. is  no  version  number  of  the  whole  system, but only of the
  65. kernel. Your version should be 1.0.
  66.  
  67. F68K  is NOT thought to be a system which is ready to use on all
  68. levels  and all computers. It shall be as large and universal as
  69. it  can  be  at a time, but not more. In order to make it larger
  70. and more universal, F68K needs YOUR help. So, if you have ported
  71. F68K  to  a  new  hardware  or  have  written  a  new tool or an
  72. application,  which  can  be  of interest to other users, please
  73. send  it to me. I will find an appropriate place of your part in
  74. the  system  and  add your name to the F68K-programmers list you
  75. find below.
  76.  
  77. ****************************************************************
  78.  
  79.  
  80.  
  81. The  F68K-kernel  is COPYRIGHTED. While using F68K you accept my
  82. ownership.
  83.  
  84.  
  85.  Copying Fees
  86.  
  87. If  you  normally  charge  a  fee for making someone a copy of a
  88. disk, you may charge the same fee for making a copy of F68K. The
  89. fee  must  be  based  solely on the cost of making the copy, and
  90. must  be  the  same  fee that you charge for a copy of any other
  91. disk.
  92.  
  93.  
  94.  Licensing
  95.  
  96. If  you  develop soft- or hardware that uses the F68K-kernel and
  97. wish  to  SELL your product along with F68K, please get in touch
  98. with   me  so  we  can  work  out  a  licensing  agreement.  The
  99. F68K-kernel  may  not  be  sold  as part of any system without a
  100. licensing  agreement.  I'll  be willing to work out an agreement
  101. that is fair to both of us.
  102.  
  103. If  you  do  not  want  to sell anything together with F68K, but
  104. nevertheless   like   it,   please  contact  me  or  the  'Forth
  105. Gesellschaft  e.V.'  in order to come to know the latest news on
  106. F68K.  Send me some (at least two) ST or DOS formatted disks and
  107. a  paid envelop with your address on it, I will register you and
  108. send  you  the latest version of F68K at all times. If the disks
  109. are  not  formatted  or the envelop is missing, I will just keep
  110. the rest.
  111.  
  112. Please  understand  that  I  cannot  give away the entire kernel
  113. listing  with  this  free  version  of  F68K.  If you are REALLY
  114. interested  in  that listing, please contact me and we will find
  115. an appropriate agreement.
  116.  
  117.  
  118.  
  119.  Documentation
  120.  
  121. As  said  above,  F68K will never become ready. So documentation
  122. will  never  be  ready, too. You will always find some essential
  123. documentation  on  the  disks in the '.TXT' files and within the
  124. sources, of course. If you would like to have the latest version
  125. of documentation, see 'Licensing'.
  126.  
  127.  
  128.  Liability
  129.  
  130. I  shall  have  no  liability or responsibility to any person or
  131. entity  with  respect to any loss or damage caused or alleged to
  132. be  caused directly or indirectly by F68K. This includes, but is
  133. not  limited  to, any interruption of service, loss of business,
  134. loss  of  information  or  that which is rendered inaccurate, or
  135. loss  of  anticipated  profits  or  ANY  OTHER  CONSEQUENTIAL OR
  136. INCIDENTAL  DAMAGES  RESULTING  FROM  THE USE OF F68K, even if I
  137. have been advised of the possibility of such damages.
  138.  
  139.  
  140.  
  141.  Acknowlegdement
  142.  
  143. I am grateful to J. Staben for many hours of discussion on FORTH
  144. specific  problems.  Thanks  to  the  members of the local group
  145. RHEIN/RUHR   of   the   'Forthgesellschaft  e.V.'  for  fruitful
  146. discussion of technical details.
  147.  
  148.  
  149. My address:
  150.  
  151.                       Dipl. Phys. J. Plewe
  152.                       Grossenbaumer Str. 27
  153.                       D-4330 Muelheim/Ruhr
  154.                              Germany
  155.                         Tel.: 0208/423514
  156.  
  157.  
  158.  
  159. You also can get copies from:
  160.  
  161. FORTH-Gesellschaft e.V.
  162. Postfach 1110
  163. D-8044 Unterschleissheim
  164. Germany
  165.  
  166. or from anyone, who is willing to make you a copy
  167.  
  168.  
  169.  
  170. ---------------------------------------------------------------
  171. These people worked at F68K (Hall of Fame)
  172.  
  173. J. Plewe                 F68K kernel, kernel extensions
  174. Laxen & Perry            M68000 Assembler
  175. Hartwig Luedemann        L&P assembler on 32 bit
  176. Dirk Kutscher            Sinclair QL loader
  177. Markus Redeker           Lots of bugs and tools, F-EDIT
  178. Reinhard Scharnagl       Disassembler
  179. Wolfgang Schemmert       Amiga loader
  180. Thomas Beierlein         OS9 loader
  181. ---------------------------------------------------------------
  182.  
  183.  
  184.  
  185.  
  186.                               Hope you enjoy the system,
  187.                               keep going forth, your's
  188.  
  189.                                         J. Plewe 
  190.  
  191.  
  192.  
  193.  
  194.  
  195. P.S. If you miss a message like 'If you like ... please send $xx
  196. to ...' here is one for you:
  197.  
  198. You may support me and F68K by sending any amount of money!!
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207. ###############################################################
  208. Introduction
  209. ###############################################################
  210.  
  211. FORTH   is   a   widespread  computer  language  that  has  been
  212. implemented  on nearly all important machines. If you have got a
  213. PC,  than you will be able to choose your system out of a set of
  214. highly  developed  FORTH implementations. If you have one of the
  215. less often sold computers, such as Mac, ST or Amiga this is true
  216. to some degree, too.
  217.  
  218. Now FORTH is a language, who's applications typically do NOT run
  219. on  such  machines,  but on single-chip or home-build computers,
  220. for example.
  221.  
  222. This  is  because  FORTH  does not care for operating systems or
  223. complicated  I/O.  It may be easily be run on a naked system. In
  224. those  cases, everyone has to develop his own FORTH environment.
  225. F68K  wants  to close this gap between the commonly used and the
  226. 'special' systems.
  227.  
  228. F68K  was  designed  to  run  on  ALL  MC68000 computers without
  229. changing  and  recompiling  or reassembling the kernel. For that
  230. reason,  the  kernel  may  not  depend on the I/O or the address
  231. configuration  of  the  target system. In order to achieve that,
  232. without trying miracles, there will have to be a loader for each
  233. machine or operating system. This loader 'knows' all the machine
  234. dependent stuff.
  235.  
  236. Porting  F68K  to  a  new  computer  means  to create a suitable
  237. loader.  Because  all loaders are similar, this is an easy task.
  238. An experienced programmer might do that before breakfeast.
  239.  
  240. So,  if  you  have  just  build  a  new MC68000 system, you will
  241. immediately  be  able  to  use  the tremendous power of a unique
  242. FORTH programming environment.
  243.  
  244.  
  245.  
  246. ###############################################################
  247. Forth-83?
  248. ###############################################################
  249.  
  250. F68K  follows the FORTH-83-standard in most cases, but it cannot
  251. be  a  real  FORTH-83  system  at  all, because it uses a 32 bit
  252. stack.  In some details it leaves FORTH-83 and turns towards the
  253. new  ANSI  standard, which is not completely defined yet. So the
  254. words  COMPILE  and  [COMPILE]  no  longer exist. They have been
  255. replaced be the more smart POSTPONE.
  256.  
  257. The old words are easily redefined:
  258.  
  259. : COMPILE        POSTPONE POSTPONE ;      IMMEDIATE  
  260. : [COMPILE]      POSTPONE POSTPONE ;      IMMEDIATE  
  261.  
  262.  
  263. There  are  slight deviations concerning control structures. See
  264. the corresponding chapter "Control Structures" for details.
  265.  
  266. The  most  important  deviation is the expansion of blocksize to
  267. 2kB.  This gives the user a full 80x25 screen for source editing
  268. (see  "Mass  storage")  and  allows  the creation of an internal
  269. forth  filesystem, called FIFI. This is described in the chapter
  270. "F68K streaminterface".
  271.  
  272. It  is  intended  that F68K shall develop towards ANSI, although
  273. the  dpANS  standard  defines  a  block  to be of a size of 1024
  274. bytes.  But  for  F68K blocks are of 2000 bytes, almost any ANSI
  275. compatible  source  will compile and run correctly, even if some
  276. bytes (2000- 1024) perhaps will be wasted.
  277.  
  278.  
  279.  
  280. ###############################################################
  281. Loader
  282. ###############################################################
  283.  
  284.  
  285. The  F68K  system consists of an F68K system image and a loader,
  286. which has to load the system image into memory and to provide it
  287. with all necessary I/O- and memory information.
  288.  
  289. So  it  becomes  possible  to  design  the  system  image  to be
  290. perfectly independent of any hardware and/or operating system.
  291.  
  292. Porting  F68K  to a new system or even a completely new hardware
  293. means  to create the appropriate loader and the system will run.
  294. Of  course,  the  loader  has  to  fit the system, so one has to
  295. follow some rules when creating the loader.
  296.  
  297.  
  298.  What the loader does
  299.  
  300. The  task  of  the loader is quite simple: it has to install the
  301. code  and  the data part of the system image into memory, invent
  302. some  good  addresses for the stacks and the TIB (Terminal Input
  303. Buffer)  and  to  store all these addresses in a given structure
  304. together  with the (absolute) addresses of the I/O functions and
  305. to  push  the  address  of  this  structure  on the returnstack,
  306. indexed  by  the address register A7. It then simply has to jump
  307. to the start of the code segment. That's all!
  308.  
  309.  
  310.        
  311.  Loading the system image
  312.  
  313. As  said  above,  the system image consists of two parts: a code
  314. and  a  data segment. Both must be loaded into memory before the
  315. system  is  ready  to  run.  This action depends on the way, the
  316. system image is stored on the mass storage device or ROM. In all
  317. cases,  it  must  be  known,  how  these  parts can be placed in
  318. memory. For example, in the original distribution, the image was
  319. created  with  an assembler under the operating system GEMDOS on
  320. Atari  ST.  So, there is an image file that consists of the code
  321. and  data  parts  and a file header. In that header, which is 28
  322. byte  large,  one  will find with an offset of two the length of
  323. the  code segment and with an offset of six the size of the data
  324. segment:
  325.  
  326.         struct header
  327.         {
  328.           int magic;
  329.           unsigned long codesize;
  330.           unsigned long datasize;
  331.           int dont_care[9];
  332.         } header;
  333.  
  334.  
  335. In  the original distribution, the integer 'magic' holds the two
  336. characters  'JP',  which  are  the  initials  of my name. So the
  337. loader  has  the possibility to check wether the given imagefile
  338. contains a valid F68K image.
  339.  
  340. One  will  have  to  load the header, fetch the named values and
  341. then  load the two parts into appropriate buffers. If the system
  342. comes  in  an other form, these informations must be given, too.
  343. The  buffers, of course, have to be larger than the sizes of the
  344. segments.  In  most  cases,  a  buffer  of  64 kbyte for code is
  345. enough. For the data segment, no limit can be predestined.
  346.  
  347.  
  348.  
  349.  I/O functions
  350.  
  351. There are five functions, that must be given by the loader:
  352.        
  353.         getting a character from the terminal, KEY
  354.         getting the terminal's status, KEY?
  355.         putting a character to the terminal, EMIT
  356.         reading an writing blocks from/to the
  357.                 mass storage device, R/W
  358.         ------------------------------------------------
  359.         reading data from a system dependent device
  360.         writing F68K data to a system dependent device
  361.  
  362.  
  363. There  is  a  defined data interface of these functions to F68K.
  364. They  all  find  theire  parameters  on  a  stack indexed by the
  365. address  register  A7,  which  is the standard F68K returnstack.
  366. They all leave outcoming parameters in the dataregister D0. Note
  367. that this data interface is the same used by common C-compilers,
  368. where  parameters are passed on the returnstack (A7). This makes
  369. it  very  simple  to  write  a loader in C. When using assembler
  370. language,  it  is  important to know, that the parameters lie on
  371. the  stack  in  reverse order to those on the F68K-stack! On the
  372. top of returnstack there always is the returnaddress. There is a
  373. simple translation from F68K-parameters to stack positions:
  374.  
  375.  
  376.         Forth:      ( para1 para2 para3 -- ret )
  377.         Stack (a7):   4(a7) 8(a7) $c(a7)   d0
  378.  
  379.  
  380. So this interface is easy-to-use even on assembler level.
  381.  
  382. The  loader  can  define  more  then  one  routine  for  all six
  383. functions. E.g. it can submit an EMIT for a terminal, a printer,
  384. a serial port and a file. There may be functions for a KEY which
  385. comes  from  the  terminal  or  the  serial  line  (not from the
  386. printer, of cource). There has to be a table for each of the six
  387. functions which has to be constructed as follows:
  388.  
  389.  
  390.         byte 0-3:   number of routines
  391.         byte 4-7:   first routine
  392.         byte 8-11:  second routine
  393.             .            .
  394.             .            .
  395.             .            .
  396.  
  397. Example:
  398.  
  399. keytable:      DC.L      2
  400.                DC.L      TERMKEY
  401.                DC.L      SERIALKEY
  402.  
  403.  
  404. The  addresses  of  theses tables are later passed to F68K. They
  405. can  be  accessed  on  FORTH-level  using the words KEYS, KEY?S,
  406. EMITS,  R/WS, READSYSES and WRITESYSES. They give the address of
  407. the  0.  byte  of the appropriate table. The first entry of each
  408. table  will be taken as the default I/O. So there is an easy way
  409. to  support  all  I/O  devices  available and to redirect I/O on
  410. FORTH-level:
  411.  
  412.  
  413. : >PRINTER ( -- )    KEYS 2 CELLS + @ ^KEY ! ;
  414.  
  415.  
  416.  
  417. Here is a description of the I/O functions and theire parameters
  418. in detail. The user has not to care about registers and the F68K
  419. stack.  F68K  saves  all  registers  before calling the loader's
  420. functions  and  sets  the  datastack  to  the  right value after
  421. return.
  422.  
  423.  
  424. a.) KEY
  425.  
  426. KEY  does  not  expect  any  parameter.  It  just  waits for the
  427. terminal  to send a character. This character is embedded as the
  428. least  significant  byte  of  long word (4 byte) and then pushed
  429. onto the stack.
  430.  
  431.         example:
  432.                
  433.         KEY:       JSR     get_key   ;the character comes in D0
  434.                    RTS
  435.  
  436.         or
  437.  
  438.         long key()
  439.         {
  440.                return (long)getch();
  441.         }
  442.  
  443.  
  444.  
  445. b.) KEY?
  446.  
  447. KEY?  does  not  expect  any  parameter. It checks the terminal,
  448. wether  there is a character available for KEY. In that case, it
  449. returns  a  TRUE flag (something <>0), otherwise a FALSE flag in
  450. register D0.
  451.  
  452.  
  453.         example:
  454.        
  455.         KEY_QUEST:   JSR     termstate      ;status comes in D0
  456.                      RTS
  457.  
  458.         or
  459.  
  460.         long key_quest()
  461.         {
  462.                return (long)kbhit();
  463.         }
  464.  
  465.  
  466.  
  467. c.) EMIT
  468.  
  469. EMIT  takes  a  character  from  the  stack and prints it on the
  470. terminal.  Some terminal emulation can be done here. After EMIT,
  471. there is no parameter on the stack.
  472.  
  473.  
  474.         example:
  475.  
  476.         EMIT:        MOVE.L  4(A7),D0        ;SP: return char
  477.                      JSR     char_out        ;print the character
  478.                      RTS
  479.  
  480.         or
  481.  
  482.         void emit(c)
  483.         long c;
  484.         {
  485.                putch((char)c);
  486.         }
  487.  
  488.  
  489.  
  490. d.) R/W
  491.  
  492. R/W  is  the  most  complex function of these four. It has three
  493. parameters  on the stack. First, there is a flag, wether reading
  494. (flag  =  0)  or  writing  shall be performed, then there is the
  495. blocknumber  and the last parameter is the (absolute) address of
  496. a  buffer.  When the flag is zero, then the block with the given
  497. number has to be loaded into the buffer at the given address. If
  498. the  flag  is  something  unequal  to zero, then the data in the
  499. buffer  at  the  given  address has to be written into the given
  500. block.  A  block  is  an  amount of 2048 byte = 2 kB on the mass
  501. storage  device.  There  are  always 2048 bytes read or written.
  502. Where  they  come  from or where they go to only concerns to the
  503. R/W  function.  F68K  does  not  care!  Because errors may occur
  504. during  load or save, R/W leaves a flag in register D0, which is
  505. nonzero in case of success.
  506.  
  507.  
  508.         example:
  509.  
  510.         *Forth parameters ( buffer block r/w? -- flag )
  511.         *stack position     4(a7)  8(a7) $c(a7)   d0
  512.         * 0(a7) is returnaddress
  513.         R_W:          TST.L   $C(A7)          ;read or write?
  514.                       BEQ     read_block
  515.         write_block:  MOVE.L  8(A7),D0        ;get block number
  516.                       ASL.L   #2,D0           ;512 byte/sectors
  517.                       MOVE.L  #4,D1           ;number of sectors
  518.                       MOVE.L  4(A7),A0        ;the buffer
  519.                       JSR     write_sectors   ;flag in D0  
  520.                       RTS
  521.         read_block:   MOVE.L  8(A7),D0        ;get block number
  522.                       ASL.L   #2,D0           ;512 bytes/sector
  523.                       MOVE.L  #4,D1          ;sectors to be read
  524.                       MOVE.L  4(A7),A0        ;the buffer
  525.                       JSR     read_sectors    ;flag in D0
  526.                       RTS
  527.  
  528.         or
  529.  
  530.         long r_w(buffer, block, rwflag)
  531.         long buffer, block, rwflag;
  532.         {
  533.                if(rwflag==0)
  534.                     return diskread(buffer, block);
  535.                       /*not shown here*/
  536.                else
  537.                     return diskwrite(buffer, block);
  538.                       /*not shown here*/
  539.         }
  540.  
  541.  
  542.  
  543. Note  that  blocks  must  not  be physical blocks on a floppy or
  544. harddisk.  They  can  also  be  emulatet,  for  example,  within
  545. streamfiles provided by an operating system.
  546.  
  547.  
  548.  
  549. e.) READSYS
  550.  
  551. READSYS allows the user to read F68K data from the system, which
  552. loaded  F68K.  In  general,  this will be a file in an operating
  553. system.  This  path is installed in order to be able to design a
  554. unique  and  system independent import function e.g. for sources
  555. in  F68K.  READSYS gets a buffer's address and the length of the
  556. buffer as arguments. If succesful, it returns -1=TRUE, otherwise
  557. 0=FALSE.
  558.  
  559.  
  560.         example:
  561.  
  562.         *Forth parameters:    ( addr  count -- flag)
  563.         *stack positions:       4(a7) 8(a7)     d0
  564.         READSYS:    TST.L   FIRST
  565.                     BNE     NOOPEN
  566.                     MOVE.L  FILENAME,A0
  567.                     BSR     OPENFILE
  568.                     MOVE.L  D0,INHANDLE
  569.         NOOPEN:     MOVE.L  4(A7),A0         ;BUFFER
  570.                     MOVE.L  8(A7),D0         ;COUNT
  571.                     JSR     FREAD
  572.                     MOVE.L  8(A7),D1         ;COUNT again
  573.                     CMP.L   D1,D0            ;error?
  574.                     BEQ     NOERROR
  575.                     CLR.L   D0               ;FALSE-flag
  576.                     BRA     RSYSEND
  577.         NOERROR:    MOVE.L  #-1,D0           ;TRUE-flag
  578.         RSYSEND:    RTS
  579.  
  580.         or
  581.  
  582.         long readsys(buffer, count)
  583.         {
  584.         static int first;
  585.         static int inhandle;
  586.  
  587.                if(first)  fopen(&inhandle,"INFILE");   /*or so*/
  588.                return (fread(inhandle,buffer,count) == count);
  589.         }
  590.  
  591.  
  592.  
  593. f.) WRITESYS
  594.  
  595. WRITESYS allows the user to write F68K data to the system, which
  596. loaded  F68K.  In  general,  this will be a file in an operating
  597. system.  This  path is installed in order to be able to design a
  598. unique  and  system independent SAVESYSTEM function in F68K. But
  599. WRITESYS  can  also be (mis)used for other purposes, e.g. output
  600. protocols or export of sources. WRITESYS gets a buffer's address
  601. and  the  length  of  the  buffer as arguments. If succesful, it
  602. returns -1=TRUE, otherwise 0=FALSE.
  603.  
  604.  
  605.         example:
  606.  
  607.         *Forth parameters:    ( addr  count -- flag)
  608.         *stack positions:       4(a7) 8(a7)     d0
  609.         WRITESYS:   TST.L   FIRST
  610.                     BNE     NOCREATE
  611.                     MOVE.L  FILENAME,A0
  612.                     BSR     CREATEFILE
  613.                     MOVE.L  D0,OUTHANDLE
  614.         NOCREATE:   MOVE.L  4(A7),A0         ;BUFFER
  615.                     MOVE.L  8(A7),D0         ;COUNT
  616.                     JSR     FWRITE
  617.                     MOVE.L  8(A7),D1         ;COUNT again
  618.                     CMP.L   D1,D0            ;error?
  619.                     BEQ     NOERROR
  620.                     CLR.L   D0               ;FALSE-flag
  621.                     BRA     WRSYSEND
  622.         NOERROR:    MOVE.L  #-1,D0           ;TRUE-flag
  623.         WRSYSEND:   RTS
  624.  
  625.         or
  626.  
  627.         long writesys(buffer, count)
  628.         {
  629.         static int first;
  630.         static int outhandle;
  631.  
  632.                if(first)
  633.                     fopen(&outhandle,"OUTFILE");  /*or so*/
  634.                return (fwrite(outhandle,buffer,count) == count);
  635.         }
  636.  
  637.  
  638.  
  639.  
  640.  Using different devices with R/W
  641.  
  642. In  some  cases there may be more than one blockoriented device.
  643. If  so,  R/W  has  to  multiplex the different devices. For that
  644. reason,  a  set  of  block  ranges  for  each  device  has to be
  645. declared.  For  example, there are a floppy drive and a harddisk
  646. and  the  floppy  gives  room  to 320 blocks. Then the following
  647. table, called ROOTTABLE has to be allocated in the loader:
  648.  
  649.  
  650.      DC.L      2         ;there are two devices
  651.      DC.L      0         ;floppy uses blocks 0-319
  652.      DC.L      320       ;capacity is 320 blocks
  653.      DC.L      320       ;block >320 are on harddisk
  654.      DC.L      1000      ;capacity of harddisk is 1000 blocks
  655.  
  656.  
  657. In  dependency  of the blocknumber, the function used by R/W now
  658. has to switch between different access mechanisms, for example
  659.  
  660.      R_W:      IF blocknumber < 320
  661.                THEN  access floppy
  662.                ELSE  access harddisk
  663.  
  664. The  word ROOTTABLE in F68K is a constant whih gives the pointer
  665. to  roottable. There is a USER-Variable called ROOTBLK, which is
  666. added  to  the  number given to BLOCK, before BLOCK uses R/W. So
  667. the  user  may  define  simple  words,  which  switch between he
  668. devices.
  669.  
  670. For example:
  671.  
  672.  
  673.      : D0:      ROOTTABLE  4 + @  ROOTBLK ! ;
  674.      : D1:      ROOTTABLE 12 + @  ROOTBLK ! ;
  675.  
  676. When  F68K  is  initialised, the first entry in the roottable is
  677. written  to the variable ROOTBLK, so this is an easy way to take
  678. one device as default.
  679.  
  680.  
  681.  Buffers in memory
  682.  
  683. F68K  needs  at  least five addresses of buffers in memory which
  684. have  to  be  allocated  by  the loader. First there are the two
  685. buffers for code and data segments. Second, there is need for at
  686. least  two  buffers  for  the data- and the returnstack. Last, a
  687. buffer  for  the  TIB must be available. The allocation of these
  688. buffers may be done according the taste of the programmer or the
  689. needs of the application.
  690.  
  691. Here are some hints:
  692.  
  693. The TIB must not be smaller than 256 bytes. It may be larger but
  694. there is no need for a larger buffer in standard cases.
  695.  
  696. The  stacks  grow  towards lower addresses, whereas TIB grows to
  697. higher  addresses. So the same pointer may be used as a base for
  698. one  of the stacks (usually the datastack) and the TIB. When the
  699. F68K dictionary is expanded, it gros towards higher addresses in
  700. code  and  data segment. It it a good advice to place the stacks
  701. at the end of availible memory and the code and data segments at
  702. the beginning.
  703.  
  704. Here is a possible memory map as an example:
  705.  
  706.  
  707.         lowest address (la):    start of code segment
  708.  
  709.                 .
  710.                 .
  711.                 .
  712.  
  713.         la + 64kb:              return stack base      
  714.                                 start of data segment
  715.                 .
  716.                 .
  717.                 .
  718.                 .
  719.                 .
  720.        
  721.         ha - 256 byte:          start of TIB, data stack base
  722.                 .
  723.         highest address (ha):   end of TIB
  724.  
  725.  
  726.  
  727. As  an  second  example, one could make the TIB buffer larger an
  728. place  the  returnstack  at  the end of TIB, so it grows towards
  729. start of TIB.
  730.  
  731.  
  732. Note  that  F68K  does  NO  error  checking  concerning stack or
  733. dictionary overflows!
  734.  
  735.  
  736.  
  737.  Starting F68K
  738.  
  739. When  the I/O functions are written, the memory is allocated and
  740. the  system  image is loaded, F68K can be started. The necessary
  741. parameters,  which  are  all known now, have to be stored into a
  742. structure  shown  below  which  address' has to be pushed on the
  743. returnstack. Then the jump into the system can be performed.
  744.  
  745.  
  746.         forthparas:
  747.         registers:     DS.L 16   ;d0,d1,d2,d3.......,a5,a6,a7
  748.  
  749.         data:          DS.L 1
  750.         code:          DS.L 1
  751.         datstk:        DS.L 1
  752.         retstk:        DS.L 1
  753.         TIBptr:        DS.L 1
  754.         codelen:       DS.L 1
  755.         datalen:       DS.L 1
  756.         emittable:     DS.L 1
  757.         keytable:      DS.L 1
  758.         keyqtable:     DS.L 1
  759.         r_wtable:      DS.L 1
  760.         readsystable:  DS.L 1
  761.         writesystable: DS.L 1
  762.         roottable:     DS.L 1
  763.   ;extensions like files, grafics, windowing can be placed here
  764.  
  765.  
  766.         or
  767.  
  768.  
  769.         struct forthparas
  770.         {
  771.               long registers[16];    /* to be filled by F68K */
  772.               void *data;
  773.               void *code;
  774.               void *datstk;
  775.               void *retstk;
  776.               void *TIBptr;
  777.               long codelen;
  778.               long datalen;
  779.               void *emittable;
  780.               void *keytable;
  781.               void *keyqtable;
  782.               void *r_wtable;
  783.               void *readsystable;
  784.               void *writesystable;
  785.               void *roottable;
  786.         /* possible extensions like files, grafics, windowing */ 
  787.         } forthparas;
  788.  
  789.  
  790.  
  791.  
  792. Example:
  793.  
  794.         MOVE.L  databot,data     ;start of data segment
  795.         MOVE.L  codebot,code     ;start of code segment
  796.         MOVE.L  tib,datstk
  797.         MOVE.L  retstack,retstk
  798.         MOVE.L  tib,TIBptr       ;same pointer for stack an TIB
  799.         MOVE.L  #$20000,datalen  ;data segment's size is 128 kb
  800.         MOVE.L  #$10000,codelen  ;code segment's size is 64 kb
  801.         MOVE.L  #EMITTABLE,emit
  802.         MOVE.L  #KEYTABLE,keytable
  803.         MOVE.L  #KEY_QUESTTABLE,keyqtable
  804.         MOVE.L  #R_WTABLE,r_wtable
  805.         MOVE.L  #READSYSTABLE,readsystable
  806.         MOVE.L  #WRITESYSTABLE,writesystable
  807.         MOVE.L  #ROOTTABLE,roottable
  808.  
  809.         MOVE.L  forthparas,-(A7)
  810.         JSR     codebot     ;jump into the system, MUST be JSR
  811.  
  812.         BRA     exit        ;when come back, then exit loader
  813.  
  814.  
  815. (retstack,  tib, databot and codebot shall be variables with the
  816. pointers  to  returnstack,  the  TIB, the start of data and code
  817. segments, respectivily)
  818.  
  819.  
  820.         or
  821.  
  822.  
  823.         set_forthparas();
  824.         f68k(forthparas);
  825.  
  826.  
  827.  
  828. Hopefully, F68K will prompt now with it's 'ok'!
  829.  
  830.  
  831. The  forthparas  are  visible from F68K simply using FORTHPARAS.
  832. This  gives  access  to the functiontables, that may be added at
  833. the   end  of  the  structure.  So  there  is  a  very  flexible
  834. possibility  to extend the F68K loaderinterface e.g. for special
  835. abilities of operating systems. There is no standardisation yet,
  836. but  I  would  suggest  to  reserve  the  first free place for a
  837. pointer  to  a table of file functions, the next for grafics and
  838. the  third  for  windowing.  The  first implementation of one of
  839. these,  which  reaches me, could set the standard, e.g. the F68K
  840. standard GEM interface.
  841.  
  842.  
  843. There   are   some  very  important  things  to  say  about  the
  844. 'registers'  area  in  the  forthparas.  The  reader should have
  845. noticed, that this area is not influenced by the loader. Indeed,
  846. this  area  will be filled by F68K itself during initialisation.
  847. All  regsiters of the loaders runtime environment will be stored
  848. here in the following order:
  849.  
  850. D0, D1, .... D7,  A0, A1, .... A7
  851.  
  852. The  value for A7 in this area (registers + 15*4) will be of the
  853. location pointed to before F68K has been called. That means that
  854. the  top  of  this  A7-stack  will point to the forthparas. This
  855. gives  the  possibility  for the I/O-functions to restore theire
  856. runtime  environment completely, including the returnstack. This
  857. can  make  sense,  when  the  I/O-functions need some registers,
  858. which  the loader has saved on the loaders returnstack for them.
  859. They  can be accessed by the pointer held within 'register'. The
  860. I/O-functions  must take care that the original A7 (that is used
  861. by F68K) will be restored before returning to F68K.
  862.  
  863.  
  864. !!! Important !!!
  865.  
  866. Some  critical operating systems need a specific set of register
  867. contents  to execute the loaders I/O-functions. F68K saves these
  868. registers  in  the  FORTHPARAS-structure  as described above. In
  869. order to make this area accessible to the loader functions, F68K
  870. places  the  absolute address of the FORTHPARAS in bottom of the
  871. (return-)stack,  below  the  parameters.  I/O-functions in those
  872. critical  environments therefore have the possibility to restore
  873. vital registers and then execute the appropriate I/O-function.
  874.  In uncritical environments, one not has to take care about this
  875. value  on  the  stack,  because it will be removed automatically
  876. when returnig control to F68K.
  877.  
  878.  
  879.  
  880.  
  881.  
  882. ###############################################################
  883. Input and output
  884. ###############################################################
  885.  
  886. All  of  the  F68K  in- and output functions are vectorized. The
  887. addresses  of  the  I/O functions are held in the USER-variables
  888. (KEY),   (KEY?),   (EMIT),   (R/W),  (READSYS)  and  (WRITESYS),
  889. respectivily.  The  appropriate  words  KEY,  KEY?,  EMIT,  R/W,
  890. READSYS  and  WRITESYS always use these vectors. These Variables
  891. are  preset  with  the  addresses  of  the F68K-words LOADERKEY,
  892. LOADERKEY?,    LOADEREMIT,    LOADERR/W,    LOADERREADSYS    and
  893. LOADERWRITESYS.
  894.  These  words  again  only  use vectors for execution. These are
  895. ^KEY,  ^KEY?,  ^EMIT,  ^R/W, ^READSYS and ^WRITESYS. If the F68K
  896. startup routine held in the USER-variable (COLD) does not change
  897. one  of these variables, then they will be filled with the first
  898. of  the  addresses  provided in the loader's I/O function tables
  899. (see  'Loader')  at  system's  entry.  The  user may store other
  900. addresses  fetched  from  these  tables  or  completely  new I/O
  901. functions  in  these  variables. When doing this, he should know
  902. about some dependencies.
  903.  It  is  important that the addresse held in ^KEY, ^KEY?, ^EMIT,
  904. ^R/W,  ^READSYS and ^WRITESYS point to functions provided by the
  905. loader.  The  must not be executed in F68K simply using EXECUTE.
  906. The  system  may crash. These functions may only be called using
  907. LOADERKEY,  LOADERKEY?, LOADEREMIT, LOADERR/W, LOADERREADSYS and
  908. LOADERWRITESYS   because   some   interfacing   concerning   the
  909. parameters has to be done. On the other hand no simple F68K-word
  910. may be stored in these vectors or the same reason.
  911.    
  912. The  words  EXPECT or TYPE use the lower level functions KEY and
  913. EMIT.  So  if  KEY is changed, all words using KEY, like EXPECT,
  914. will  be  changed, too. So KEY influences even the input editor.
  915. If  the  user  wants  to  avoid  this, he will be able to change
  916. EXPECT   and   TYPE,   too.   They   are   vectorized  with  the
  917. USER-variables (EXPECT) and (TYPE).
  918.  
  919.  
  920.  
  921. ###############################################################
  922. Mass storage
  923. ###############################################################
  924.  
  925.  
  926. F68K   supports   mass  storage  devices  like  floppies  and/or
  927. harddisks.  For  F68K  has  to  be  a  portable system, the mass
  928. storage  support  must  be  portable, too. This is only possible
  929. when  NOT using existing file systems or other access mechanisms
  930. on F68K level.
  931.  
  932. F68K accesses the mass storage device in portions of 2 kb = 2048
  933. bytes.  This quantity is called a BLOCK. Each block has a unique
  934. number. The range of this number does not depend on F68K, but on
  935. the  implementation  of  the  read/write primitive in the loader
  936. (see 'Loader').
  937.  
  938. When  refering  a specific block by it's number, e.g.
  939.  
  940.  
  941. 27 BLOCK ( blocknumber -- address )
  942.  
  943.  
  944. F68K  finds an appropriate buffer using the word BUFFER and then
  945. passes  the  buffer's address and the number of the block to the
  946. word  R/W,  which  then  calls  the  read/write  function in the
  947. loader. R/W can be seen as the end of the mass storage interface
  948. on  the side of the device, whereas BLOCK is the end on the side
  949. of  F68K.  BUFFER  than  is  something like a tunnel between the
  950. ends.
  951.  
  952. According  to  the  stack  comment for BLOCK, it expects a block
  953. number and returns a address. This address points to the buffer,
  954. where  the  data  of  the  block was read in. Writing to a block
  955. means  writing  into  that  buffer.  If  the buffer is marked as
  956. changed,  using the word UPDATE, it will be written back to disk
  957. again  when  the  buffer  is  used for another block or the user
  958. executes  FLUSH, which saves all UPDATE'ted buffers to disk. But
  959. in  the  normal case, the user does not have to take care wether
  960. is  block  is  read from or written to disk. The user may access
  961. mass  storage  in  the  same way as he does with memory. So, the
  962. F68K blocks are a kind of virtual memory.
  963.  
  964. Although  the  physical size of a block on a disk is 2 kb (often
  965. four  sectors), the size of a buffer is only 2000 bytes. This is
  966. because  the  first 48 bytes of each block are used for internal
  967. management  of  blocks.  The  user  may access these 48 bytes by
  968. using  negativ  offsets on the address returned by BLOCK, but he
  969. should  be very carefull. By the way, the reserved bytes will be
  970. used,  for  example, to realize block organisation on a disk, so
  971. that  streams  of  blocks may be refered by name, in a way it is
  972. done with files on 'normal' operating systems.
  973.  
  974. So 2000 bytes of data may be used freely.
  975.  
  976.  
  977.  
  978.  Handling Buffers
  979.  
  980. In  a  virtual  memory  system,  buffers have to be handled. The
  981. buffers  are  the  connection  between  virtual and real memory.
  982. Buffer handling in F68K is performed by the word BUFFER:
  983.  
  984.  
  985. BUFFER ( blocknumber -- address )
  986.  
  987.  
  988. Every  F68K  system must have at least one buffer, but any other
  989. number is possible, too. More buffers cause less disk activity.
  990.  
  991. A F68K buffer has the following structure:
  992.  
  993.        14 bytes header
  994.      2048 bytes block data
  995.  
  996. in detail:
  997.  
  998.      $0   pointer to next buffer
  999.      $4   physical number of block in the data buffer
  1000.      $8   logical number of block in the data buffer
  1001.      $C   UPDATE flag
  1002.      $E   data buffer, 2048 bytes
  1003.  
  1004.  
  1005. All  buffers used by F68K are linked together in a cyclic linked
  1006. list.  The  first  four  bytes  of  a  buffer  are  used for the
  1007. necessary  pointer.  There is a USER-variable called PREV, which
  1008. contains a pointer to the buffer most recently refered.
  1009.  
  1010. The  second four bytes contain the number of the block which has
  1011. been  refered.  This  is  the number which is passed to R/W when
  1012. reading  or  writing  the  block. In contrast, the number in the
  1013. third  entry in the buffer's header is a logical blocknumber. It
  1014. is  only used when using a 'higher' disk organisation, where the
  1015. disk is divided into several streams of blocks. Then this number
  1016. may  be the logical number of a block within such a stream. Last
  1017. there  is  a  word (2 bytes) which is used as a flag, wether the
  1018. block has been altered after loading from disk.
  1019.  
  1020. When the user executes BLOCK or BUFFER, then a new buffer has to
  1021. be  allocated.  The  mechanism  to  do  that  is  quite  simple.
  1022. Bufferallocation  is always done with BUFFER. BLOCK calls BUFFER
  1023. itself. BUFFER expects a blocknumber on the stack. Now, first it
  1024. checks, wether the refered block is already loaded in one of the
  1025. existing  buffers.  The  word  ?CORE  does  this  check. For all
  1026. buffers  are  linked  in  a  cyclic  list, ?CORE starts with the
  1027. buffer the USER-variable PREV points to, and compares the number
  1028. on  the  stack  with  the second value in the buffers header. On
  1029. equality,  ?CORE stops returning the buffer's address, otherwise
  1030. it  fetches  the  link  to  the next buffer until it reaches the
  1031. buffer  it started with. If no equality has occured, it returnes
  1032. a  FALSE- flag. If ?CORE does not result in FALSE, BUFFER simply
  1033. returns the buffer ?CORE found. If ?CORE could not find a buffer
  1034. containing  the  data  of the desired block, BUFFER will use the
  1035. buffer  following  the  one,  which  PREV  points to. But before
  1036. returning  the  address  of  that  buffer,  it  first checks the
  1037. UPDATE-flag  in  the header. If it is set, the buffer is written
  1038. back  to  disk  to  the  block that is indicated by the physical
  1039. blocknumber  in  the  header. It then clears the UPDATE-flag and
  1040. writes the address of that buffer to the USER-variable PREV. Now
  1041. the  buffer  is  allocated  and BLOCK may load it's data into it
  1042. using R/W.
  1043.  
  1044. The  sense  of this mechanism becomes clearer when observing the
  1045. chronological  order  in which buffers are used. When taking the
  1046. next  buffer  in  the cyclic linked list, it is clear, that this
  1047. one  is  the  'oldest' among all buffers. It is a natural aim to
  1048. use  the  buffer,  which  is the at least recently used. This is
  1049. perfectly done by this mechanism.
  1050.  
  1051.  
  1052.  Notes
  1053.  
  1054. All which is said above is valid when using the kernel directly.
  1055. BLOCK  and  BUFFER  are  DEFERred words, which may be redirected
  1056. e.g.  by  the blockstream system. The description above is meant
  1057. for the primitives (BLOCK and (BUFFER, which are originally used
  1058. by BLOCK and BUFFER.
  1059.  
  1060. There  is  another technical detail to be mentioned. To simplify
  1061. access,  BLOCK  first  compares  the given blocknumber, which it
  1062. converts into a physical blocknumber by adding ROOTBLK, with the
  1063. content  of  the global variable LASTBLK. If they are identical,
  1064. BLOCK  returns  with  the  content of LASTBUF. Otherwise the way
  1065. described  above  is  gone  and  LASTBLK and LASTBUF are updated
  1066. accordingly.
  1067.  
  1068.  
  1069. ###############################################################
  1070. Pointer and addresses
  1071. ###############################################################
  1072.  
  1073.  
  1074. This  chapter  is  very  important,  because  F68K distinguishes
  1075. between  two  types  of  pointers  or addresses. In general, all
  1076. addresses  are  relativ!  There  is  no  occasion in F68K, where
  1077. absolut addresses are used.
  1078.  
  1079. In most cases, the user has not to care for address handling. He
  1080. may use the '@' and '!' operators as usual.
  1081.  
  1082. There are some very special situations, where the user has to be
  1083. careful.  These  situation  occur,  when addresses of executable
  1084. code, e.g. addresses within the code segment, occur.
  1085.  
  1086. Then  the  user  has  to  remember,  that  F68K  consists of two
  1087. segments: the code- and the datasegment.
  1088.  
  1089. 'Normal'  addresses,  which  may  be operands to '@' and '!' are
  1090. always  offsets into the datasegment. That is clear, because the
  1091. user normally wants to access data, not code.
  1092.  
  1093. So, if the user defines a variable,
  1094.  
  1095.  
  1096. VARIABLE X
  1097.  
  1098.  
  1099. then  a  header  and  space for the data is allocated within the
  1100. datasegment,  whereas  the runtimecode of VARIABLE is located in
  1101. the  codesegment.  X  gives  the  offset  of the data within the
  1102. datasegment on the stack. So '@' or '!' work with these offsets.
  1103.  
  1104. Now consider the following problem:
  1105.  
  1106. The user wants to compile some words 'by hand', so he has to get
  1107. the appropriate codeaddress and to compile it.
  1108.  
  1109. Here is a somewhat unusual version of ': NIP     SWAP DROP ;'
  1110.  
  1111.  
  1112. : NIP ( n1 n2 -- n2 )    [ ' SWAP JSR,  ' DROP JSR, ] ;
  1113.  
  1114.  
  1115. This  version  compiles  a  different code than the natural one.
  1116. This  comes  from  the  fact,  that F68K internally does not use
  1117. 'JSR,'  for  codegeneration.  As  indicated by the name, it only
  1118. generates  a  JSR-code and does not care for relativ branches or
  1119. macro  expansion ('JSR,' generates an additional MOVE-operation,
  1120. which  is  of no interest in this context. 'JSR,' generates code
  1121. of a defined length, which can be useful sometimes).
  1122.  
  1123. In  fact, F68K uses the word 'COM,' for codegeneration. The word
  1124. '  (tick)  gets  the address of the following word in form of an
  1125. offset  into  the CODEsegment. So no '@' or '!' is possible with
  1126. that  address!!  'JSR,'  knows this fact and it is only natural,
  1127. that  words,  which  generate  code,  use  addresses  out of the
  1128. codesegment.
  1129.  
  1130. But  for 'COM,' there is a difficulty: it should know wether the
  1131. word  to  be  compiled  has  to  be  expanded  as  a  macro. The
  1132. corresponding  information is located in the control word in the
  1133. header  of  that  word. But the header is in the DATAsegment! So
  1134. 'COM,'  needs  the address of the word's header. This address is
  1135. found using the word H' (header tick):
  1136.  
  1137.  
  1138. : NIP ( n1 n2 -- n2 )     [ H' SWAP COM,  H' DROP COM, ] ;
  1139.  
  1140.  
  1141. In  order to make the relation between ' and H' clearer, one may
  1142. express ' by H':
  1143.  
  1144.  
  1145. : ' ( -- addr )     H' @ ; 
  1146.  
  1147.  
  1148.  
  1149.  Addressconversion between segments
  1150.  
  1151. There  are  some other occasions, where the user wants to access
  1152. data  within  the codesegment. E.g. he wants to access the value
  1153. of  a  variable  without  using  the  variable's  name (for what
  1154. reason?).  Then  he  has  to  know  something  about a variables
  1155. structure,  which  is the same for all CREATE structures. In the
  1156. codesegment,  there is the runtime-code of a variable. It is the
  1157. code  generated  by  'JSR,' (see 'Generating Code'), that means,
  1158. that there are 8 bytes of code for each variable. Behind these 8
  1159. bytes   there  is  a  pointer  to  the  data.  This  pointer  is
  1160. datasegment-relative,  of  course.  But the pointer itself is in
  1161. the  codesegment,  so  it  has  to  be  accessed there. For that
  1162. reason,   one   has   to  define  a  word,  which  transforms  a
  1163. codesegment-relative into a datasegment- relative address:
  1164.  
  1165.  
  1166. : CODE>DATA ( Caddr -- Daddr )  SYSBOT + $8000 + ;     
  1167.  
  1168.  
  1169. SYSBOT  is  a  constant  that  gives  the  address (datasegment-
  1170. relative)  of the beginning of the codesegment. The $8000 has to
  1171. be added because the codeaddresses are relative to the middle of
  1172. the first 64k-codesegment (see 'Generating Code' again). Now the
  1173. variables data can be accessed:
  1174.  
  1175.  
  1176. VARIABLE X
  1177.  
  1178. ' X            ( pointer to runtimecode of a CREATE-word )
  1179. 8 +            ( pointer now behind runtimecode          )
  1180. CODE>DATA      ( make it relative to datasegment ...     )
  1181. @              ( so @ can get the pointer to the data    )
  1182. @              ( now gets the value                      )
  1183.  
  1184.  
  1185. By the way, 'X @' does the same and is a bit less complicated. 
  1186.  
  1187.  
  1188.  
  1189.  Converting from/to absolute addresses
  1190.  
  1191. In  some  cases  it  could  be  necessary  to obtain the absolut
  1192. address  from  a  relativ.  This  could  be  useful  in  writing
  1193. CODE-definitions. This conversion is done with the word
  1194.  
  1195.  
  1196. >ABS    ( reladdr --- absaddr )
  1197.  
  1198.  
  1199. So  '0  >ABS'  gives  the  absolute start of the datasegment. To
  1200. convert   codesegment  relativ  addresses,  there  is  the  word
  1201. >ABSCODE.  '0  >ABSCODE'  gives  the  absolute  location  of the
  1202. codesegment.
  1203.  
  1204. When using machinecode in CODE-definitions, two addressing modes
  1205. are  defined to simplify access to F68K data and code. These are
  1206. DATA)  and  CODE),  which  have  to  be  pronounced 'datasegment
  1207. indirect' and 'codesegment indirect', respectivily. Theire usage
  1208. is simple:
  1209.  
  1210.  
  1211. Variable X
  1212.  
  1213. CODE X@
  1214.      ' X # d0       .l move        \ get pointer to X in codeseg
  1215.      8 # d0         .l addq        \ put it behind code
  1216.      d0 code) d0    .l move        \ get pointer to data
  1217.      d0 data) sp -) .l move        \ get data
  1218. next  end-code
  1219.  
  1220.  
  1221. This  is the same way to access a variables value as it was used
  1222. in  the  example  above in high-level. It is important, that the
  1223. register holding the F68K-address is a dataregister d0-d7!
  1224.  
  1225.  
  1226. Last,  there  should  be  the  possibility  to  access  absolute
  1227. addresses,  that  means  to  convert an absolute address into an
  1228. relative F68K-address. This is performed with the word
  1229.  
  1230.  
  1231. (ABS)    ( absaddr -- reladdr )
  1232.  
  1233.  
  1234. So '0 (ABS) @' reads the absolute address 0 (and gives the reset
  1235. SSP). (ABS) and >ABS are reversing each other.
  1236.  
  1237. Corresponding  to  (ABS)  there  is  (ABSCODE) which converts an
  1238. absolute into a codesegment relative address.
  1239.  
  1240.  
  1241. !!!!  Important  Rule:  If  a  location  in  the  datasegment is
  1242. referenced,   the   pointer  must  always  be  relative  to  the
  1243. datasegment. If a location in the codesegment is referenced, the
  1244. pointer  must  always  be  relative  to  the  codesegment. NEVER
  1245. compile  a  reference  to  codesegment as an pointer relative to
  1246. datasegment!  If  a  conversion  (CODE>DATA)  has to be made, it
  1247. ALWAYS has to be made a runtime!
  1248.  
  1249. Example:  accessing the VIEW-information in the codesegment
  1250.  
  1251.  
  1252. : TEST
  1253.      ...   ['] A_WORD CODE>DATA 4-  @   ... ;
  1254.  
  1255.  
  1256. is correct, but
  1257.  
  1258.  
  1259.      ... [ ' A_WORD CODE>DATA 4- ] LITERAL @   ... ;
  1260.  
  1261.  
  1262. is WRONG.
  1263.  
  1264.  
  1265. If  you  wonder  why, remember that code- and datasegment may be
  1266. placed  anywhere  in  memory.  So  it  is  not possible to fix a
  1267. location  in  the  codesegment  with  an  address relativ to the
  1268. datasegment.  If  the segments will be placed somewhere else the
  1269. next time, the intersegment-relative pointer will probabely have
  1270. wrong values!! Think of it!
  1271.  
  1272.  
  1273.  '>R', 'R>' and 'R@'
  1274.  
  1275. Additionally,  something very important has to be said about the
  1276. words '>R', 'R>' and 'R@'. In traditional implementations, these
  1277. words  simply  push,  pop  or fetch a word from/to the datastack
  1278. to/from  the returnstack. In F68K, this words do some conversion
  1279. with  the  data  while  moving  between the stacks. When pushing
  1280. something  to  the  returnstack,  it  is  always treated like an
  1281. address and it is converted into a absolute machineaddress. This
  1282. has to be done because this should be possible:
  1283.  
  1284.  
  1285. : FOO     ['] FOO1 >R ;
  1286.  
  1287.  
  1288. The  codeaddress  of  'FOO1'  is pushed onto the returnstack, so
  1289. that  it  will  be  executed when reaching the 'RTS' instruction
  1290. compiled  by  ';'.  For  the M68000 does not know anything about
  1291. F68K  pointer-  treatment, the address on top of the returnstack
  1292. has  to be a valid machineaddress. So the conversion from a F68K
  1293. codesegment  relative  address  (permitted  by  '[']')  into  an
  1294. absolute  address is performed by '>R'. So '>R' implicitely uses
  1295. '>ABSCODE'. This has to be reconverted, if the data returns from
  1296. the  returnstack.  So 'R>' and 'R@' implicitely use '(ABSCODE)'.
  1297. For  this  reason  it  is not allowed to push something onto the
  1298. returnstack using '>R' and later get an explicite access using a
  1299. sequence like
  1300.  
  1301.  
  1302. RP@ @
  1303.  
  1304.  
  1305. because  the  reconversion  is  omitted  in  this  case. A legal
  1306. sequence to do things like that is
  1307.  
  1308.  
  1309. RP@ @ (ABSCODE)               \ do the right conversion
  1310.  
  1311.  
  1312. doing the conversion 'by hand'.
  1313.  
  1314. This  highly  compatible use of of '>R', 'R>' and 'R@' has to be
  1315. paid  with  a  little  more  effort accessing inline-data in the
  1316. codesegment.  Inline-values  normally are accessed using the top
  1317. of  returnstack  as a pointer to the value. For now this pointer
  1318. is  an  absolute  machineaddress,  it has to be converted before
  1319. access  using  '@' can be performed. There are two possibilities
  1320. to  do  that. They are very hard to explain, so I let an example
  1321. do the explanation:
  1322.  
  1323.  
  1324. : GETINLINE ( -- N )
  1325.      R@ >ABSCODE (ABS)             \ convert address
  1326. \     RP@ @ (ABS)                  \ ... this is more simple
  1327.      @                             \ access inline-data
  1328. \     R> 4+ >R ;                   \ increase returnaddress
  1329.      4 RP@ +! ;                    \ ... or this way
  1330.  
  1331.  
  1332. : TEST ( -- 27 )
  1333.      GETINLINE [ 27 CODE, ] ;
  1334.  
  1335.  
  1336. Note  that  'CODE,'  has  to  be taken to create the inline-data
  1337. instead of ','.
  1338.  
  1339.  
  1340.  
  1341.  
  1342. ###############################################################
  1343. Header
  1344. ###############################################################
  1345.  
  1346.  
  1347. Each  word defined in F68K is preceeded by a header. This header
  1348. contains information about the name of the word, the location of
  1349. the  code  and  some  flags.  Additionally,  all  headers of one
  1350. vocabulary  (see  'Vocabularies')  are linked together as a long
  1351. chain  of  words. Each header holds a pointer to the header last
  1352. defined  before  (in  the  same  vocabulary). The structure of a
  1353. header is very simple:
  1354.  
  1355.  
  1356.      -----------
  1357.      | Control |                                  \ 16 bit
  1358.      =====================
  1359.      | Ptr to code       |       'CFA'            \ 32 bit
  1360.      =====================
  1361.      | Ptr to last header|       'LFA'            \ 32 bit
  1362.      =====================---------------------
  1363.      | Cnt| Name of word as counted string ...|
  1364.      ------------------------------------------
  1365.  
  1366.  
  1367. In the controlword, some bits have a special meaning:
  1368.  
  1369. Bit 0:    the word is SMUDGE. The vocabulary searching word FIND
  1370. will ignore words with this bit set. REVEAL will set this bit to
  1371. zero.
  1372.  
  1373. Bit 1:    the  word is immediate. When compiling, this word will
  1374.  be executed, nevertheless.
  1375.  
  1376. Bit 2:    the  word  is restrict. This means that this word must
  1377. not  be  executed  interactivily.  It  can  only  be used in the
  1378. compiling state (STATE=-1).
  1379.  
  1380. Bit 3:    the  word  is  a macro. This bit will be set, when the
  1381. word  has  successfully  been  compiled using the defining words
  1382. 'M:'  or  'MCODE'.  When  the F68K-macrooption is on (MACRO ON),
  1383. then  the  F68K-compiler  will  not  compile a reference to this
  1384. word, but will copy the complete code.
  1385.  
  1386.  
  1387. Bits 8-15:    in  this  byte  the  length of the code is stored.
  1388. This  number  is measured in 16bit. The final RTS-instruction at
  1389. the end of the code is not counted. This number is important for
  1390. F68K-macrocompiler.
  1391.  
  1392.  
  1393. The  pointer  to code holds the 32bit-address of the code. It is
  1394. called  the  'CodeFieldAddress'  or  'CFA'.  This is the address
  1395. given by the word ' ' '. This address is already relative to the
  1396. codesegment,  so  '@' or '!' must not be used with this address!
  1397. (If  you  wonder why, remember that code- and datasegment may be
  1398. placed  anywhere  in  memory.  So  it  is  not possible to fix a
  1399. location  in  the  codesegment  with  an  address relativ to the
  1400. datasegment.)  One  longword  before beginning of code, there is
  1401. the  VIEW-field. This field contains a 32bit-value, which is the
  1402. number  of  the  physical  sourceblock, where this word has been
  1403. defined.  The  VIEW-field  was placed by the code instead by the
  1404. header  because so it will be possible to find the source again,
  1405. even  when  the  header has been removed or destroyed. To access
  1406. this number, a source sequence like this is necessary:
  1407.  
  1408.  
  1409. ' A_WORD CODE>DATA             \ find codeaddress an convert it
  1410. 4-  @                          \ fix pointer to the 32bit-word
  1411.                                \ before the code and fetch the
  1412.                                \ VIEW-information
  1413.  
  1414.  
  1415. Be  carefull  not to compile the address of the VIEW-field after
  1416. conversion (CODE>DATA). Conversions have to be done at runtime!!
  1417. (see: 'Pointer and Addresses')
  1418.  
  1419.  
  1420. The next field contains the pointer to the last recently defined
  1421. header   (in   the   same   vocabulary).   It   is   called  the
  1422. 'LinkFieldAddress'  or  'LFA'.  This is an ordinary F68K-pointer
  1423. (relative  to  datasegment). This link is used when searching in
  1424. the  vocabulary. The LFA of the first word in each vocabulary is
  1425. NULL (0).
  1426.  
  1427. After the linkfield there is the name of the word preceeded by a
  1428. countbyte. This name is a standard FORTH-string.
  1429.  
  1430.  
  1431.  
  1432. ###############################################################
  1433. USER variables
  1434. ###############################################################
  1435.  
  1436.  
  1437. FORTH  passes  it's  parameters on a stack. This is the 'normal'
  1438. procedure.  But  sometimes  it  is  usefull  to have some 'real'
  1439. variables, which can be refered by name, equal to variables used
  1440. in  other  languages.  They  are declared in most cases with the
  1441. defining word VARIABLE.
  1442.  
  1443. But  since  FORTH is a multitasking, sometimes multiuser system,
  1444. this datatype cannot be used in all situations. VARIABLEs can be
  1445. changed  by  all tasks and users. So no task or user can rely on
  1446. the content of a variable. If a variable has to be bound to only
  1447. one  task  or user, it has to be defined using the defining word
  1448. USER.
  1449.  
  1450. USER-variables are all stored together in one field. The size of
  1451. that field is determined by the kernel and now is 2 kbyte. There
  1452. are about 300 bytes used by the kernel itself, so there is romme
  1453. enough.  When  creating a USER-variable, the offset of the first
  1454. free  entry  in the USER-area is stored together with the header
  1455. of the defined word. The access occurs with this offset together
  1456. with  a  pointer  to  the  base of the USER-area. The pointer is
  1457. always  held  within  the  machine-register  D5.  Switching this
  1458. register    to   another   USER-area   means   to   switch   all
  1459. USER-variables.  Each  task  has  it's  own USER-area, so it may
  1460. change these variables without taking effect on other tasks.
  1461.  
  1462. There are some memory buffers connected to a task, which may not
  1463. be  shared  with  others. These is e.g. the vocabulary stack. In
  1464. order  to  allow  an automatical allocation of all these buffers
  1465. when  creating a new task, F68K provides a simple mechanism: all
  1466. these buffers are organized in a linked list. Behind the pointer
  1467. for  the  link  there will be the length of the buffer in bytes.
  1468. The  address  of  the first element of that list is stored in he
  1469. USER-  variable  USERBUFS.  So  it  is very easy to allocate all
  1470. necessary buffers.
  1471.  
  1472. Hint:
  1473. Sometimes  it  is  necessary  to put even the block buffers into
  1474. this  list.  This  depends  on  the  nature  of the taskswitcher
  1475. (interruptive  or cooperative). The one and only buffer provided
  1476. with  the kernel has two longwords in front of it left empty, so
  1477. that is possible without taking completely new buffers.
  1478.  
  1479.  
  1480.  
  1481. ###############################################################
  1482. Values and locals
  1483. ###############################################################
  1484.  
  1485.  
  1486. F68K  provides  two  types  of data, which are not common to all
  1487. FORTH  implementation,  but  will  be  fixed  in the coming ANS-
  1488. standard.  These  are  VALUE  and  LOCAL,  which  are similar in
  1489. implementation and usage:
  1490.  
  1491.  
  1492. <n> VALUE <name>
  1493.  
  1494. <n> LOCAL <name>
  1495.  
  1496.  
  1497. VALUE  and  LOCAL  create an initialised datatype, which behaves
  1498. just like a constant. So
  1499.  
  1500.  
  1501. 27 VALUE FOO
  1502. FOO .               --> 27
  1503.  
  1504.  
  1505. In contrast to simple constants, VALUEs and LOCALs are changeble
  1506. using the prefix 'TO'. So
  1507.  
  1508.  
  1509. 35 TO FOO
  1510. FOO .               --> 35
  1511.  
  1512.  
  1513. This is the same with LOCAL.
  1514.  
  1515.  
  1516. LOCAL  differs  from  VALUE,  of  cource. LOCAL can only be used
  1517. within  ':'-definitions  and  creates  a  local  value, which is
  1518. visible just before the next ';' is compiled.
  1519.  
  1520.  
  1521. : ADD ( a b -- a+b )
  1522.      LOCAL B  LOCAL A
  1523.      A B + ;
  1524.  
  1525. B                   --> unknown!
  1526. 3 5 ADD .           --> 8
  1527.  
  1528.  
  1529. To see how LOCALs can be changed, here a somewhat silly example:
  1530.  
  1531.  
  1532. : ADD2 ( a b -- a+b )
  1533.      0 LOCAL A   0 LOCAL B
  1534.      TO B  TO A
  1535.      A B + ;
  1536.  
  1537.  
  1538. By the way, the best and fastest way to define 'ADD' in F68K is
  1539.  
  1540.  
  1541. MACRO @  MACRO ON
  1542. M: ADD ( a b -- a+b )
  1543.      + ;
  1544. MACRO !
  1545.  
  1546.  
  1547. So 'ADD' is as fast as '+' itself.
  1548.  
  1549.  
  1550. LOCALs are very useful when there are a lot of parameters on the
  1551. stack or when parameter handling is difficult. The use of LOCALs
  1552. in  definitions like 'ADD' should be avoided, because they use a
  1553. lot of memory and time.
  1554.  
  1555. The  use of VALUEs instead of VARIABLEs is strongly recommended,
  1556. because  they are faster and need less memory. Often, the syntax
  1557. becomes clearer. The user should not use VALUEs where a CONSTANT
  1558. would  do  the  job,  too, because nothing is shorter and faster
  1559. then a CONSTANT.
  1560.  
  1561.  
  1562.  Implementation
  1563.  
  1564. VALUE  and  LOCAL both create same code. LOCAL produces an extra
  1565. call  to  allocate the memory for the data. Both use an in-line-
  1566. address to find the data. VALUE creates the following code:
  1567.  
  1568.  
  1569.    +--------------+-----------------+-------------+
  1570.    | CALL fetcher | in-line-address | CALL storer |
  1571.    +--------------+-----------------+-------------+
  1572.  
  1573.  
  1574. It  is important, that the fetcher is compiled using a 'JSR,' so
  1575. that the 'CALL fetcher' always uses 8 bytes.
  1576.  
  1577. The  in-line-address  points  to  the  data  for VALUEs and to a
  1578. pointer  to  the  data  for LOCALs. The difference is due to the
  1579. fact,  that  this  pointer  for  a  LOCAL  has to be modified at
  1580. runtime,  and  so  it  has to be fixed, when the code segment is
  1581. placed  in  ROM. The pointer holds a fixed address of a location
  1582. in  the  data segment, where the pointer to data will written at
  1583. runtime (the data segment may not be in ROM).
  1584.  
  1585. The  task  of  the  fetcher is to get the in-line-address and to
  1586. fetch  the  data  from  there. When referencing or compiling the
  1587. VALUE,  always  the fetcher is used. It is 'TO', which activates
  1588. the  storer.  'TO' finds the codeaddress of the following VALUE-
  1589. type  using  `'`,  adds  an  offset  of  12  bytes (8 byte 'CALL
  1590. fetcher',  4 byte in-line-address) and executes or compiles this
  1591. address  itself,  corresponding the content of the USER-variable
  1592. STATE.
  1593.  
  1594. The  storer  then gets the in-line-address from in front of it's
  1595. call and stores the data on the stack in this location.
  1596.  
  1597. LOCAL  additionally  compiles  a  'CALL  initer' in front of the
  1598. sequence above. This 'initer' links 4 bytes off the returnstack,
  1599. initialises  this  place  with  the  value from top of stack and
  1600. pushes  the  address  of  a  routine  on  the returnstack, which
  1601. unlinks  the  allocated  space  on the returnstack at exit-time.
  1602. This is very complicated to explain, although it is very simple.
  1603. The  user  should take a glance at the sources. There are only a
  1604. few lines of assembler in the kernel.
  1605.  
  1606.  
  1607.  Restrictions
  1608.  
  1609. Some  little  restrictions  occur  when  using  LOCALs. The user
  1610. should  be very careful manipulating the returnstack. Defining a
  1611. local means to alter the first two elements on returnstack.
  1612.  
  1613.  
  1614. : TEST
  1615.      ...                      \ something
  1616.      >R
  1617.      0 LOCAL TEMP             \ never!
  1618.      R>                       \ never!
  1619.      ...                      \ something further
  1620. ;                             \ crash!
  1621.  
  1622.  
  1623. One could use
  1624.  
  1625.  
  1626. R> R> R> SWAP >R SWAP >R
  1627.  
  1628.  
  1629. instead  of  'R>',  but  this  should  be avoided for reasons of
  1630. readability.
  1631.  
  1632.  
  1633.  
  1634. ###############################################################
  1635. Vocabularies
  1636. ###############################################################
  1637.  
  1638.  
  1639. F68K supports a vocabulary structure, which allows usage of same
  1640. namens  for  different  words.  Vocabularies  are lists of words
  1641. compiled  into  them.  There  is a search order of vocabularies,
  1642. which  is followed when F68K tries to find a word extracted from
  1643. the  source.  When the user has created words with the same name
  1644. in  different  vocabularies,  F68K  will  take  the first one it
  1645. finds,  e.g. the one within the vocabulary, which is the highest
  1646. in  the  search  order.  The  gives  the  possibility to compile
  1647. different  version  of  a  word just by installing a appropriate
  1648. search  order. Applications should always have an own vocabulary
  1649. and   sub-  vocabularies,  they  are  hierarchic,  so  that  the
  1650. applications words can easily be seperated from the words inside
  1651. the   development   environment.  The  main  vocabulary  of  the
  1652. environment  is  called  FORTH.  System  words  like DUP, ROT or
  1653. FORGET are located in that vocabulary.
  1654.  
  1655.  
  1656.  Usage
  1657.  
  1658. Vocabularies  are  created  using  the  defining word VOCABULARY
  1659. followed by the desired name e.g.
  1660.  
  1661.  
  1662. VOCABULARY FOO
  1663.  
  1664.  
  1665.  
  1666.  
  1667.  
  1668.  Implementation
  1669.  
  1670. The  implementation  had to be somewhat complicated, in order to
  1671. preserve the ROMability of the code segment.
  1672.  
  1673. Vocabularies  consist  of  a normal header, which may be deleted
  1674. when  headers  are  removed, too, and a set of pointers in both,
  1675. code and data segment.
  1676.  
  1677.  
  1678. There  first  is  the  runtime code of a vocabulary with a fixed
  1679. length of six bytes (JSR <32b-address>) in the codesegment. Then
  1680. there  is a pointer (ptr1) to a field in the data segment, which
  1681. is  normally  located  behind the header of the vocabulary. This
  1682. pointer  (ptr3)  contains  the  address of the link field of the
  1683. last  word  in  the  vocabulary.  Behind this pointer there is a
  1684. second  one  (ptr4)  which points back into the code segment. It
  1685. points  to  the location just behind the runtime code, where the
  1686. pointer  (ptr1)  into  data segment is. So code and data segment
  1687. are linked forth and back in a vocabulary.
  1688.  
  1689. Vocabularies  themselves  are  linked  together  with  a pointer
  1690. (ptr2)  which  is  located  with  an  offset  of  8  behind  the
  1691. runtimecode.  The  last  element  of  the vocabulary list can be
  1692. found  in  the  USER- variable VOC-LINK. It is important to know
  1693. that this pointer gives addresses within the codesegment, so '@'
  1694. cannot be used. The user has to apply 'CODE@' instead.
  1695.  
  1696.  
  1697.  
  1698.         CODE                             DATA
  1699.  
  1700.  +--> ptr2 of former vocabulary
  1701.  |
  1702.  |
  1703.  |   JSR dovoca                         header
  1704.  |   ptr1 --------------------------->  ptr3 -----+
  1705.  |        ^---------------------------  ptr4      |
  1706.  +---ptr2                                         |
  1707.                                                   |
  1708.                                                   |
  1709.                                                   |
  1710.                                     last header  <+
  1711.  
  1712.  
  1713.  
  1714.  
  1715. ###############################################################
  1716. Interpreter
  1717. ###############################################################
  1718.  
  1719. The  subroutine INTERPRET to be decribed here is normally called
  1720. the  'outer  interpreter'  to  make clear that there is an inner
  1721. interpreter   as   well.  For  F68K  does  not  have  any  inner
  1722. interpreter because it creates native code, this distinction has
  1723. not to made here.
  1724.  
  1725. The  F68K  interpreter is invoked using the word INTERPRET. This
  1726. will  interpret  or compile the strings given by WORD until WORD
  1727. will return the address of a string which will cause NULLSTR? to
  1728. answer  with  true. This will be the case when the input stream,
  1729. coming  from  the  terminal  or a block, is exhausted. INTERPRET
  1730. could be implemented in the following manner:
  1731.  
  1732.  
  1733. : INTERPRET ( -- )
  1734.         BEGIN
  1735.               BL WORD  NULLSTR?
  1736.         WHILE
  1737.               PARSER
  1738.         REPEAT ;
  1739.  
  1740.  
  1741. As it can be seen, PARSER will do most of the work consuming the
  1742. input.  PARSER  is  a  DEFERred word which can either compile or
  1743. interpret  the  strings supplied by WORD. This depends on wether
  1744. the  actual  state of the system (STATE) is compiling (STATE<>0)
  1745. or  interpreting  (STATE=0).  In  the  first  case,  PARSER will
  1746. execute COMPILER, in the latter it will execute INTERPRETER. The
  1747. switch between this to words for PARSER is done by the words '['
  1748. and ']' which are implemented like that:
  1749.  
  1750.  
  1751. : [ ( -- )
  1752.         0 STATE !  ['] INTERPRETER IS PARSER ;
  1753.  
  1754. : ] ( -- )
  1755.        -1 STATE !  ['] COMPILER    IS PARSER ;
  1756.  
  1757.  
  1758. INTERPRETER  and  COMPILER  each  take  the  address of the next
  1759. string  in  the  input  stream as an input parameter and do both
  1760. yield no output parameter:
  1761.  
  1762.  
  1763. COMPILER ( addr -- )
  1764. INTERPRETER ( addr -- )
  1765.  
  1766.  
  1767. This  implementation  makes  it  possible to use the interpreter
  1768. itself  for  applications just by replacing the word executed by
  1769. PARSER.
  1770.  
  1771. A  simple  example for that is to list all words that would have
  1772. been  isolated  by  WORD  on  the  terminal  instead  of  really
  1773. interpreting them:
  1774.  
  1775.  
  1776. : PRINTER ( addr -- )
  1777.         COUNT TYPE CR ;
  1778.  
  1779.  
  1780. : :LIST ( n -- )       \ <n> :LIST
  1781.         ['] PRINTER IS PARSER
  1782.         LOAD
  1783.         ['] INTERPRETER IS PARSER  ;
  1784.  
  1785.  
  1786.  
  1787. or to show extended use of DEFER-words:
  1788.  
  1789.  
  1790. : :LIST ( n -- )       \ <n> :LIST
  1791.         ['] PARSER CELL+ CODE@  PUSH   \ save runtime of PARSER
  1792.         ['] PRINTER IS PARSER
  1793.         LOAD ;
  1794.  
  1795.  
  1796.  
  1797.  
  1798.  
  1799. ###############################################################
  1800. Control structures
  1801. ###############################################################
  1802.  
  1803. F68K  provides  control structures, which are identical to those
  1804. used in FORTH-83 systems in most cases. But in some points, F68K
  1805. turns   to   the   new   ANSI   standard.   This   concerns  the
  1806. BEGIN..WHILE..REPEAT(UNTIL)-structure.  In  F68K,  any amount of
  1807. WHILEs are allowed, but there must be a THEN for each additional
  1808. WHILE behind REPEAT in order to resolve the references left open
  1809. by  WHILE. It is also possible to use WHILEs together with AGAIN
  1810. or  UNTIL, but there has to be a THEN for each WHILE. This gives
  1811. the  structure  some  more  flexibility,  for  there may be code
  1812. between UNTIL and THEN:
  1813.  
  1814.  
  1815. ... BEGIN ...  WHILE ... WHILE ... UNTIL ... THEN ... THEN
  1816.  
  1817.  
  1818. It  seems  to  be clear, that a REPEAT can always be replaced by
  1819. 'AGAIN  THEN'  with  the  additional  possibility  to place code
  1820. between AGAIN and THEN.
  1821.  
  1822.  
  1823. The other structures behave as usually. The following structures
  1824. are available:
  1825.  
  1826.  
  1827. IF ... (ELSE) ... THEN
  1828. BEGIN ... AGAIN
  1829. BEGIN ... WHILE ... REPEAT
  1830. BEGIN ... WHILE ... (WHILE) ... REPEAT ... (THEN)
  1831. BEGIN ... WHILE ... AGAIN ... THEN
  1832. BEGIN ... (WHILE) ... UNTIL ... (THEN)
  1833. DO ... LOOP
  1834.  
  1835.  
  1836. The  word  LEAVE is used to leave a DO...LOOP. EXIT is forbidden
  1837. between  DO  and LOOP because DO...LOOP holds some parameters on
  1838. the  returnstack.  ANSI says there has to be a word UNLOOP which
  1839. removes these parameters, so 'UNLOOP EXIT' should be possible.
  1840.  
  1841.  
  1842.  
  1843. ###############################################################
  1844. Reducing the kernel
  1845. ###############################################################
  1846.  
  1847. When  using  F68K  on  little  machines,  where not mass storage
  1848. device  is connected and memory is spare, then it can be usefull
  1849. to cut off some words concerning mass storage from the kernel in
  1850. order  to save memory. This incudes the one diskbuffer installed
  1851. in the kernel. So there is the possibility to save more than 2kB
  1852. of expensive memory. Here it is:
  1853.  
  1854.  
  1855. ' UPDATE FENCE !         \ set FENCE a bit lower
  1856. FORGET UPDATE            \ and forget the word before diskbuffer
  1857.  
  1858.  
  1859. From  now  on,  no  UPDATE,  (LOAD or LOAD will be available and
  1860. there  will  be no buffer for the BLOCK- and BUFFER-words. BLOCK
  1861. and  BUFFER assume that there always is at least one buffer. For
  1862. this  is  not the case now, it should be strictly avoided to use
  1863. these words. The result would be unpredictable.
  1864.  
  1865. Sources,  of  course,  now  only can be typed in by hand or been
  1866. downloaded from a server.
  1867.  
  1868.  
  1869.  
  1870.  
  1871. ###############################################################
  1872. The F68K streaminterface
  1873. ###############################################################
  1874.  
  1875. 'Normal'  computers  have 'normal' interfaces for using files on
  1876. mass  storage  devices.  For  F68K  is  a very special thing, it
  1877. follows, that is must have a very special fileinterface.
  1878.  
  1879. Speaking  more  exactly, it is not a real fileinterface, because
  1880. it  does not interface commonly known files. 'Files' in F68K are
  1881. a  concatenation  of blocks. So they are called BLOCKSTREAMS. It
  1882. is a blockstream interface to be described here.
  1883.  
  1884. I  want  to  replay  briefly  the  ideas,  that  lead to such an
  1885. interface:
  1886.  
  1887. First  I  was  discontented with the too small editing area when
  1888. using  the  classical  1k-blocks. I wanted to use my full 80x25-
  1889. screen to write my sources. So for 80x25 make 2000 characters, I
  1890. had  to  take  2k  for a block, because no mass storage device I
  1891. know  allows  the  usage  of 2000 bytes as a blocksize (not in a
  1892. simple  manner). So there they are, 48 unused bytes. That nearly
  1893. broke  my  heart. As pain makes creative, there quickly came the
  1894. idea  to  use  these  48  bytes to design a simple file-, sorry,
  1895. blockstreaminterface.  The blocks just had to be linked together
  1896. forward and backward and some blocks had to used as directories.
  1897. That's all! So far history, now the present.
  1898.  
  1899. The  interface  was  designed  to  be  loaded immediately on the
  1900. kernel.  So  no  sophisticated FORTH-features could be used. The
  1901. imagefile created with the streaminterface loaded should be used
  1902. as the new kernel.
  1903.  
  1904. The  'normal'  block  management  words like BLOCK or LOAD exist
  1905. within  blockstreams,  too.  So the user does not ave to learn a
  1906. new  block  handling.  '1  LOAD' will load the first block as it
  1907. ever  does,  but now the first block is not the first block on a
  1908. disk, e.g. first track, first sector, but the first block within
  1909. a   blockstream.   There  no  longer  is  a  dependency  of  the
  1910. blocknumber used on high level F68K and the physical blocknumber
  1911. given the the R/W primitive.
  1912.  
  1913. A  blockstream  is a simple bidirectional linked list. The first
  1914. longword  within  the  unlucky  48  bytes  of  a  physical block
  1915. contains  the  physical  blocknumber of the following block. The
  1916. second  longword  holds the preceeding. If there is no following
  1917. or preceeding, for all blockstreams have a beginning and an end,
  1918. these  longwords  will  enumerate  to  '-1'.  Behind  these  two
  1919. longwords, there is a 16-bit statusword, which decides about the
  1920. type (data, directory,..., see below) of this block. So 10 Bytes
  1921. of the wasted diskspace are used now.
  1922.  
  1923. Here is the first important note: the first block has the number
  1924. '1',  not '0'. This was done because in a blockstreamsystem that
  1925. contains  a lot of blockstreams, there are a lot of first block,
  1926. of  course.  Due  to  the  fact, that block '0' cannot be loaded
  1927. using  the word LOAD, this would create a lot of unusable blocks
  1928. of 2k each. I dont like to waste anything.
  1929.  
  1930.  
  1931. Here is the structure:
  1932.  
  1933.  
  1934.  
  1935.      |   block 1    |
  1936. +--->|--------------|
  1937. |    |              |----+
  1938. |    |--------------|    |
  1939. |    |      -1      |    |
  1940. |    +--------------+    |
  1941. |                        |
  1942. |                        |    |   block 2    |
  1943. |                        +--->|--------------|<---+
  1944. |                             |              |    |
  1945. |                             |--------------|    |
  1946. +-----------------------------|              |    |
  1947.                               +--------------+    |
  1948.                                                   |
  1949.                                                   .
  1950.                                                   .
  1951.                                                   .
  1952.                                                   .
  1953.      |   block n    |                             |
  1954.      |--------------|                             |
  1955.      |      -1      |                             |
  1956.      |--------------|                             |
  1957.      |              |-----------------------------+
  1958.      +--------------+
  1959.  
  1960.  
  1961.  
  1962. Only the actual block in use 'knows' where to find the following
  1963. or the preceeding block. The blockstream's information is stored
  1964. locally.  There  is  no  need  for  something  like  a FAT (File
  1965. Allocation   Table)   as   a  globally  known  place  where  all
  1966. informations about files are stored.
  1967.  
  1968.  
  1969. This has many advantages:
  1970.  
  1971. -    it  fits  to  the  problen.  The  unused 48 bytes are local
  1972. storage  capacity  and  can  therefore  only  be used in a local
  1973. context.
  1974.  
  1975. -    it  is very save. When working with FATs the destruction of
  1976. the physical location on the device, where the FAT is stored, is
  1977. a  fatal  and  unrecoverable error. Destroying local information
  1978. only causes local damages, which can be recovered sometimes.
  1979.  
  1980. -    it  is  completetly  independent  from  any device specific
  1981. characteristics.  F68K  does  not  care  for  the  nature of the
  1982. device.
  1983.  
  1984. -    very large devices can be managed. About 2^31 2k-blocks are
  1985. a lot of storage capacity.
  1986.  
  1987. -    it is simple.
  1988.  
  1989.  
  1990. But it has disadvantages, too:
  1991.  
  1992. -    it  is  NOT  very fast. Especially in large blockstreams of
  1993. some  hundreds of blocks it is a hard job to find a block with a
  1994. high  number  when  a block with a low number was used last. All
  1995. blocks  between  them  will have to be read. One can work around
  1996. this disadvantage using short blockstreams and many buffers.
  1997.  
  1998.  
  1999. Each  blockstream  has  a unique name. These names are stored in
  2000. special  directory  blocks. Each directory entry holds the name,
  2001. the  length  and the physical number of the first block of a the
  2002. corresponding  stream.  Additionaly there is a status word. This
  2003. status  words  decides  wether  the  described  blockstream is a
  2004. 'normal'  blockstream containing user data or a directory again.
  2005. Hence,  the directory structure is hierachic. The user can build
  2006. tree-like directories as they are used within other filesystems,
  2007. too.
  2008.  
  2009. The  physical  block 0 of each device will be a directory block,
  2010. the so called rootdirectory.
  2011.  
  2012.  
  2013. An  entry  in  a  directory  block  describing a blockstream has
  2014. following simple structure:
  2015.  
  2016.  
  2017. +---------------------------------------------------+
  2018. |name of blockstream, max 30 characters|frst|len |st|
  2019. +---------------------------------------------------+
  2020.                                          ^    ^   ^
  2021.                                          |    |   |
  2022.     phys. number of first block ---------+    |   |
  2023.                                               |   |
  2024.     length of blockstream --------------------+   |
  2025.                                                   |
  2026.     status: 0=datastream, 1=directory ------------+
  2027.  
  2028.  
  2029. For  each  entry needs 40 bytes, one directory block can hold 50
  2030. entries.  If  more entries are needed, then a directory consists
  2031. of  more  than  one block, which are organized like datastreams.
  2032. Expansion of a directory occurs automatically, the user does not
  2033. have to take care.
  2034.  
  2035.  
  2036.  
  2037.  Implementation
  2038.  
  2039. The  implementation  of  the  words  that  are  needed to handle
  2040. blockstreams  are  divided into two levels. First there is a set
  2041. of  words  which can be used in :-definitions and have something
  2042. of the character of an operating system call.
  2043.  
  2044. Second  there  is  a  set of words wich can be used typing shell
  2045. commands. The second level depends on the first.
  2046.  
  2047.  
  2048. The  words  of  the second level will probably be used first, so
  2049. they  are  decribed  first.  All  words  here allow the usage of
  2050. pathnames.   A   pathname   is   a   list   of  directories  and
  2051. subdirectories   which   all   must  exist.  The  names  of  the
  2052. directories  are  seperated  by  '/'-characters.  If  the  first
  2053. character of a pathlist is a '/', too, then the path is searched
  2054. beginning  from  the  root directory. Otherwise search starts in
  2055. the actual directory.
  2056.  
  2057. Example:  suppose the user to be in the directory MYDIR. In this
  2058. directory   there   is   a  subdirectory  called  YOURDIR.  Then
  2059. '/MYDIR/YOURDIR/TESTSTREAM'  and  'YOURDIR/TESTSTREAM'  refer to
  2060. the same blockstream.
  2061.  
  2062. This  a  common  syntax  in  many operating system so no further
  2063. description about pathname is given here.
  2064.  
  2065. Different  devices  can be accessed via the pathname putting the
  2066. devicenumber  and  a  colon  in front of a pathlist. No slash is
  2067. allowed behind the colon, or the device is ignored.
  2068.  
  2069. '1:MYDIR/TEST'  will  take  the stream TEST from device 1 in the
  2070. path  '/MYDIR/'  whereas  '1:/MYDIR/TEST' will search the actual
  2071. device.  So  for  other  devices  than  the  current  always the
  2072. complete pathname has to be given!
  2073.  
  2074.  
  2075.  
  2076. MOUNT ( -- )        usage:  MOUNT
  2077. This  will  initialise  a blockstream system copied to a device.
  2078. For  directories  contain  physical  blocknumbers,  they are not
  2079. portable  to  other  devices, where other blocknumbers are used.
  2080. MOUNT  makes  the  blockstream  system fit to the actual device.
  2081. Note  that  only  a  system,  that  has  been  UNMOUNTed, can be
  2082. mounted.  Always  make  sure  that  you are working with MOUNTed
  2083. systems  only.  Oterhwise  malfunction  is guaranteed. It is not
  2084. possible to doubly MOUNT a system.
  2085.  
  2086.  
  2087. UNMOUNT ( -- )      usage:  UNMOUNT
  2088. This  will prepare a blockstream system to be copied to an other
  2089. device.  From all physical blocknumbers contained in the system,
  2090. the number of the first physical block on the actual device will
  2091. be  substracted.  A  later  mount  will  reverse that procedure.
  2092. Always make sure that you are working with MOUNTed systems only.
  2093. Oterhwise  malfunction  is  guaranteed.  It  is  not possible to
  2094. doubly UNMOUNT a system.
  2095.  
  2096.  
  2097. MAKE ( -- )         usage:  MAKE <name>
  2098. This  will  create  a blockstream with length 1 in store it into
  2099. the  actual  directory  or  in the directory given together with
  2100. <name>.
  2101.  
  2102.  
  2103. USE ( -- )          usage:  USE <name>
  2104. This  will  open the blockstream with the name <name> for usage.
  2105. Now the words BLOCK, LOAD or BUFFER refer to that blockstream. A
  2106. STREAM:  structure called USESTREAM will be filled with the data
  2107. about the selected stream.
  2108.  
  2109. Notice  that  if  a blockstream has been created with MAKE, then
  2110. USE must be supplied additionally.
  2111.  
  2112.  
  2113. DEL ( -- )          usage:  DEL <name>
  2114. This  will  delete  the  blockstream with the given name. If the
  2115. stream  has  former  been USEd, the F68K word created there will
  2116. not be deleted!
  2117.  
  2118.  
  2119. MORE ( n -- )       usage:  <n> MORE
  2120. This  will extend the blockstream which is currently in USE by n
  2121. further blocks. They will be appended to the end of the stream.
  2122.  
  2123.  
  2124. LESS ( n -- )       usage:  <n> LESS
  2125. This  will  reduce the blockstream currently in USE by n blocks.
  2126. They will be taken from the end of the stream.
  2127.  
  2128.  
  2129. INSERT ( where amount -- )   usage:  <where> <amount> INSERT
  2130. This  will insert <amount> blocks at the position <where> in the
  2131. blockstream.
  2132.  
  2133.  
  2134. EXPEL ( where amount -- )    usage:  <where> <amount> EXPEL
  2135. This  will  cut  <amount> blocks out of the current blockstream.
  2136. The  block <where> will not be cut, it remains in the stream. To
  2137. remember  this, remember that the first block of a stream cannot
  2138. be  EXPELled. E.g. 3 2 EXPEL will cut the block 4 and 5 from the
  2139. stream.
  2140.  
  2141.  
  2142. MAKEDIR ( -- )      usage:  MAKEDIR <name>
  2143. This will create a subdirectory with the given <name>.
  2144.  
  2145.  
  2146. DELDIR ( -- )       usage:  DELDIR <name>
  2147. This  will delete a directory. Notice that this directory has to
  2148. be  empty,  e.g. it may contain nor streams neither directories,
  2149. otherwise an error condition exists.
  2150.  
  2151.  
  2152. CD ( -- )           usage:  CD <name>  or  CD
  2153. This  will change to the directory given in <name>. If no <name>
  2154. is  given,  then  the  actual  directory  path is printed on the
  2155. terminal.
  2156.  
  2157.  
  2158. DIR ( -- )          usage:  DIR
  2159. Shows the content of the current directory.
  2160.  
  2161.  
  2162. DIRECT ( -- )       usage:  DIRECT
  2163. Switches  the  blockstreamsystem  of. Now BLOCK, LOAD and BUFFER
  2164. access  the  physical  blocks  again.  The  variable  ROOTBLK is
  2165. deleted.
  2166.  
  2167.  
  2168. STREAMS ( -- )      usage:  STREAMS
  2169. Invokes the blockstreamsystem. Now BLOCK, LOAD and BUFFER access
  2170. the  logical  blocks  within the system. The variable ROOTBLK is
  2171. cleared and has not to be changed!
  2172.  
  2173.  
  2174.  
  2175. On  the other hand, there are a lot of low-level functions. Some
  2176. of them correspond directly with theire high-level counterparts.
  2177. The low level functions are more flexible and therefor take more
  2178. parameters.  There  are  a  lot  of things that can only be done
  2179. using  the  low-level  words  of  the stream-interface. The most
  2180. important words will be decribed here.
  2181.  
  2182.  
  2183. NEXTBLOCK or LINKNEXT ( physblk -- next-physblk )
  2184. Get   the  link  to  the  next  physical  blocknumber  within  a
  2185. blockstream.  This  is necessary when using systemvariables like
  2186. BLK.  In former times one could ind the preceeding block by 'BLK
  2187. @  1-'.  These times are gone. Now it is 'BLK @ LASTBLOCK'. Note
  2188. that  the physical number is returned. Words like BLOCK, LOAD or
  2189. BUFFER  may  not  be  applied  to that number. The words (BLOCK,
  2190. (LOAD   and  (BUFFER  have  to  be  used  instead.  The  logical
  2191. blocknumber  during  LOAD is hold in the USER-variable SBLK. The
  2192. user should be very careful not to mix up BLK and SBLK.
  2193.  
  2194.  
  2195. LASTBLOCK or LINKLAST ( physblk -- last-physblk )
  2196. Same as NEXTBLOCK, but in the other direction. See notes there.
  2197.  
  2198.  
  2199. SBLK ( -- addr )
  2200. This is a USER-variable which contains the number of the logical
  2201. block actually loaded. Use SBLK instead of BLK when working with
  2202. blockstreams.
  2203.  
  2204.  
  2205. BCREATE ( name length -- flag )
  2206. Creates  a blockstream with the given length. The name has to be
  2207. a  counted  string.  The returned flag is 0 when successful. The
  2208. flag  has  value  <>0 for different reasons, that cannot be seen
  2209. from  the  flag.  Errorconditions are a lack of diskspace or the
  2210. stream to be created already exists.
  2211.  
  2212.  
  2213. BDELETE ( name -- flag )
  2214. Deletes  a  blockstream from the directory. The name has to be a
  2215. counted string. The flag is 0 when successful. An errorcondition
  2216. exists when the stream does not exist. The user has to take care
  2217. that  no stream-structure connected with the deleted stream will
  2218. be used after deletion. (be VERY careful!)
  2219.  
  2220.  
  2221. DCREATE ( name -- flag )
  2222. Creates a subdirectory. The name has to be a counted string. The
  2223. flag  is  0 when successful. An errorcondition exists when there
  2224. is  not enough diskspace to create the directory, which needs at
  2225. least one block.
  2226.  
  2227.  
  2228. DDELETE ( name -- flag )
  2229. Deletes  a  directory.  The name has to be a counted string. The
  2230. flag  is  0  when  successful. An errorcondition exists when the
  2231. directory does not exist.
  2232.  
  2233.  
  2234. CHANGEDIR ( name -- flag )
  2235. Changes  to  the  given  directory. The name has to be a counted
  2236. string.  The  flag  is  0  when successful. Changing a directory
  2237. means to put the physical number of the directory block into the
  2238. USER-  variable  DIRECTORY.  An  errorcondition  exists when the
  2239. given directory does not exist.
  2240.  
  2241.  
  2242.  
  2243. ###############################################################
  2244. Lineeditor
  2245. ###############################################################
  2246.  
  2247. When  porting  F68K  to  a  new  system, the terminal control is
  2248. sometimes  very  hardware/OS-dependent.  So a full screen editor
  2249. cannot work without changes, because this editor has to move the
  2250. cursor,clear  the  screen, ... and so on. In order to be able to
  2251. do this changes, there is a primitive lineeditor, which works on
  2252. the  2k-blocks.  All actions of this editor are invoked from the
  2253. F68K  commandline.  They  allow  a  rather  fast and comfortable
  2254. change  in  textlines.  I  have  created  this  editor when F68K
  2255. consisted  of  the  kernel only. I had to CMOVE strings into the
  2256. blocks. After doing this, the lineeditor is really comfortable.
  2257.  
  2258.  
  2259. LIST ( nr -- )
  2260.      Displays the screen with the number given. The first column
  2261. of  the  screen  will contain the linenumbers with BASE 25. This
  2262. number has to be used for all other actions with the editor. The
  2263. blocknumber  is  saved  in  the variable SCR. For most terminals
  2264. only  have  80x25  characters,  LIST  will  wait for a key to be
  2265. pressed, otherwise the first line would always scroll away.
  2266.  
  2267. L ( -- )
  2268.      Lists  the block listed last again. It uses the number held
  2269. in SCR.
  2270.  
  2271. N ( -- )
  2272.      Lists  the following block. This will be the block
  2273. "SCR @ 1+".
  2274.  
  2275. B ( -- )
  2276.      Lists the last block. This will be the block "SCR @ 1-".
  2277.  
  2278. R ( -- )    \ R <nr>
  2279.      Shows  the  row  <nr>.  <nr> has to be given in BASE 25. So
  2280. there  is  one  digit only. The appropriate numbers are shown by
  2281. LIST.
  2282.  
  2283. C ( -- )    \ C <nr>
  2284.      Selects  the column <nr> (decimal). This will be the actual
  2285. writing position.
  2286.  
  2287. $ ( -- )    \ $ <string>~
  2288.      Write the string <string> to the position selected by R and
  2289. C. '~' is the delimiter of the string.
  2290.  
  2291. Example:
  2292. R h C 25 $ Hallo~
  2293.  
  2294. will insert the string "Hallo" in row 17 and column 25.
  2295.  
  2296.  
  2297. D ( -- )
  2298.      Deletes a character at the position selected with R and C.
  2299.  
  2300. DM ( -- )    \ DM <nr>
  2301.      Delete  Multiple;  Deletes  <nr> characters at the position
  2302. given by R and C.
  2303.  
  2304. DL ( -- )    \ DL <nr>
  2305.      Delete  Line;  Deletes  the line <nr>. <nr> has to be given
  2306. with BASE 25.
  2307.  
  2308. IL ( -- )    \ IL <nr>
  2309.      Insert Line; Inserts a line at line <nr> (BASE 25).
  2310.  
  2311. GL ( -- )    \ GL <nr>
  2312.      Get Line; Copies the given line <nr> (BASE 25) into special
  2313. buffer.
  2314.  
  2315. PL ( -- )    \ PL <nr>
  2316.      Put  Line;  Inserts  the  line from the buffer at the given
  2317. linenumber (BASE 25).
  2318.  
  2319.  
  2320. The  user should be aware that this lineeditor is not simple, it
  2321. is  primitive.  No  error-  or rangechecking is done. It is very
  2322. easy  to  destroy the screen or to insert unEMITable characters.
  2323. The  user  will not see them, but the compiler will. So the user
  2324. has to be very carefull using the lineeditor.
  2325.  
  2326.  
  2327.  
  2328. ###############################################################
  2329. Fullscreen Editor
  2330. ###############################################################
  2331.  
  2332. F68K  comes with a very simple full screen editor. Actually this
  2333. editor  was  one the first programs I ever wrote in FORTH. It is
  2334. capable to do the most necessary things only. In contrast to the
  2335. lineeditor  it  is  quite  save  and  comfortable.  No manual is
  2336. necessary to use it. It is invoked using the command L ( nr -- )
  2337. or  V ( -- ), where V edits the screen most recently edited with
  2338. L. A simple help can be read when typing ^?.
  2339.  
  2340. The editor needs some cursor manipulation words. These should be
  2341. preloaded.  For details see the blockstream VT52-TERMINAL, where
  2342. all desired words (and more) are defined.
  2343.  
  2344. The  cursor is moved around using the keys ^E, ^X, ^S and ^D. If
  2345. keyboard  in  use has cursorkeys, then the keycodes in the table
  2346. of  actions  in  the editor's source can be changed easily. This
  2347. table can be extended, too.
  2348.  
  2349. I  hope  that  one of the F68K users will write a better editor,
  2350. which  could  support  some  functions  of  the streamsystem, in
  2351. future.
  2352.  
  2353.  
  2354.  
  2355. ###############################################################
  2356. F-EDIT
  2357. ###############################################################
  2358.  
  2359. Markus  Redeker  has  written  a  new  fullscreen  editor, which
  2360. should  be  installed  instead of the one described above. It is
  2361. much  more  pleasant  but  uses  some  more facilities of a VT52
  2362. terminal.  It  is possible to make the editor fit into different
  2363. environments  and  different  keycodes.  So  it  is  not  longer
  2364. necessary   to  use  only  the  keycodes  of  a  ASCII-keyboard.
  2365. Cursorkeys or functionkeys may be used as well.
  2366.  Here is the original documentation written by Markus:
  2367.  
  2368.  
  2369.              The F-EDIT screen editor (Version 1.0)
  2370.  
  2371.  
  2372. 1. How to get started (if F-EDIT is already installed)
  2373.  
  2374. Start  F-EDIT the usual way by typing <blk#> L to edit the block
  2375. <blk#>  of the USEd file. If this is the first block you edited,
  2376. F-EDIT  will  ask  for  your  ID.  Enter  your  initials and the
  2377. current  date.  They  will be written automatically on the upper
  2378. right corner of every block you have changed.
  2379.    The  edited  FORTH  block  fills  the  whole  screen  of  the
  2380. computer;  messages  and  questions  are  displayed  on the last
  2381. line.  To  distinguish  them  from  the  edited  text,  they are
  2382. displayed inverse.
  2383.    The  use  of  the keys varies on different computers; to find
  2384. out  which key invokes which function, type the traditional HELP
  2385. key  of your computer (usually the key marked HELP, or that used
  2386. as  HELP  key  by most other programs) and you will see the help
  2387. block  with the ID you entered before on its upper right corner.
  2388. Read  it  and  type any key to resume to the edited FORTH block.
  2389. Read  also  the following sections to understand the help screen
  2390. better.
  2391.  
  2392.  
  2393. 2. Some unusual features
  2394.  
  2395. Current line:
  2396.  begins at cursor position (C) and ends 80 characters later:
  2397.  
  2398.                                  Cxxxxxxxxxxxx...
  2399.                   ...xxxxxxxxxxxx
  2400.  
  2401. This  convention  makes  the line stack much more useful, but be
  2402. aware of it if you want to delete a line.
  2403.  
  2404.  
  2405. String input:
  2406.  F-EDIT  displays  the  previous  content  of the edited string.
  2407. Enter  either  the  entire  new string - or nothing if you don't
  2408. want to change it. (Sorry, no input editing.)
  2409.  
  2410.  
  2411. User's ID:
  2412.  After  reading  it,  F-EDIT  stores  the identifier on the help
  2413. screen  and  reads  it again when the system is started the next
  2414. time.  So  you can leave F68K, work in the operating system, and
  2415. start  F68K  again without the need of entering always your name
  2416. and the date. (This is specially useful after a crash...)
  2417.  
  2418.  
  2419. 3. Words
  2420.  
  2421. l ( blk# -- )
  2422.  
  2423.   edits the block of the USEd file with number <blk#>.
  2424.  
  2425. v (      -- )
  2426.  
  2427.   calls  the  editor  without  initializing  it: usually you can
  2428. continue  where you stopped editing before; when an error occurs
  2429. while loading, the cursor is placed where the error occurred.
  2430.  
  2431.  
  2432. 4. Structure of the program
  2433.  
  2434. The  program consists of two files: the file F-EDIT contains the
  2435. main  program  and  a  "system  file"  contains system dependent
  2436. definitions  and  the  help  block.  It shall be named after the
  2437. computer it is meant for: in my case it is called ATARI-EDIT.
  2438.  
  2439.  
  2440. 5. Writing a System File
  2441.  
  2442. 5.1. Loading the main program F-EDIT and call EDITOR vocabulary
  2443.  
  2444. 5.2. Definition of the key table
  2445.  
  2446.  The key table consists of definitions of the form
  2447.  
  2448.                        <key> --> <action>
  2449.  
  2450. where  <action>  is one of the internal words of the editor that
  2451. do  the  real  work,  and  <key>  is  the number of the key that
  2452. invokes  that  action.  Which number you have to take depends on
  2453. the  definition  of EDIT-KEY (see below). The possible <action>s
  2454. can be found in ATARI-EDIT.
  2455.       Please  use  the  key  table  of ATARI-EDIT as a model for
  2456. your  own  key  table  to  make  a  computer change easier. (The
  2457. ATARI-  EDIT  key  table  is  designed  to  be  as compatible as
  2458. possible to all FORTH screen editors I know.)
  2459.  
  2460. 5.3. I/O words
  2461.  
  2462.  (The  words  REVERSE_VIDEO  and  NORMAL_VIDEO  are  expected to
  2463. exist by F-EDIT.)
  2464.  
  2465. The following words are DEFERred:
  2466.  
  2467.    EDIT-KEY    ( -- key )
  2468.  
  2469.  is  used instead of KEY by the editor to treat also the special
  2470. keys  (cursor  keys,  HELP  key,  ALT etc.) which are not ASCII.
  2471. EDIT-KEY  waits  like KEY until a key is pressed and returns its
  2472. number.  The  editor  uses  the  result <key> only to compare it
  2473. with  the  values  in the key table; therefore you can code your
  2474. keys  how  you  like  it (and have to do it, because there is no
  2475. standard  code). You can use all 32 bits of <key> - that is more
  2476. than usually needed but was easier to program.
  2477.         Of  course  the  editor  needs  also  ASCII  characters.
  2478. Therefore  EDIT-KEY stores the ASCII number of the key (if there
  2479. is  one)  to  the  8bit variable CHAR; it is taken from there if
  2480. <key> is not found in the key table.
  2481.  
  2482.  
  2483.    SCREEN-I/O  ( -- )
  2484.  
  2485.  prepares  the  screen  for  editing,  by  making it possible to
  2486. write  on  the  last  position  of  the  last line, and by other
  2487. system-dependent actions.
  2488.  
  2489.  
  2490.    LINE-I/O    ( -- )
  2491.  
  2492.  switches  back to the normal i/o mode by undoing the actions of
  2493. SCREEN-I/O.  The  editor  calls LINE-I/O also before EXPECTing a
  2494. string,  which  happens  in  inverse mode. So DO NOT switch from
  2495. inverse to normal display!
  2496.  
  2497.  You  have to take care of the cursor yourself, because there is
  2498. no  common  way  to  handle  it.  Some  programs  show  it  only
  2499. expecting  an input, others always. On Atari, I prefer the first
  2500. method because it is a bit faster.
  2501.  
  2502.  
  2503. 5.4. Help block
  2504.  
  2505.  The  help  block  is usually the last block of the System File.
  2506. Store its absolute position in the variable HELPBLK by writing
  2507.  
  2508.           BLOCKSTREAM ALSO   BLK @ NEXTBLOCK HELPBLK !
  2509.  
  2510.  in  the last but one block. Defining a help block is absolutely
  2511. necessary,  because  the  editor  uses  the  value of HELPBLK to
  2512. check  whether  a  system  file  has  been loaded and refuses to
  2513. start if HELPBLK = 0.
  2514.  
  2515.  
  2516. 6. Bugs & other insects
  2517.  
  2518. A  system  crash  caused  by F-EDIT seems unlikely (if F-EDIT is
  2519. installed  right),  but  there  are  some details that may cause
  2520. problems:
  2521.  
  2522.  -  F-EDIT  refers  to the help block by its absolute number. If
  2523. you  have  changed the disk (which is possible at least with the
  2524. ATARI  loader),  HELP  would  show  you a block with less useful
  2525. information.
  2526.   More  problems  arise  when  you  also  invoke  the  "Get  ID"
  2527. function:  F-EDIT  reads  the ID from the help screen and writes
  2528. it  back  afterwards.  So,  if you see some nonsense as previous
  2529. ID, just press RETURN to let it how it was before.
  2530.  
  2531.  -  The  messages  will  be displayed in a better way as soon as
  2532. F68K allows it.
  2533.  
  2534.  
  2535.  
  2536. ###############################################################
  2537. Possible errors
  2538. ###############################################################
  2539.  
  2540. This chapter shall prevent the users from possible errors, which
  2541. are  known  to me. Some of them I made myself a couple of times.
  2542. There is no order in these notes. I wrote them down like I found
  2543. them.
  2544.  
  2545.  
  2546. -  If a blockstream has just been created using MAKE, it must be
  2547. prepared for use with USE. USE is VERY likely to be forgotten. A
  2548. common (errornous) sequence is
  2549.  
  2550.  
  2551. MAKE test
  2552. 10 MORE
  2553.  
  2554.  
  2555. Now  there  is  a blockstream 'TEST' with one block and an other
  2556. blockstream has ten blocks more.
  2557.  
  2558.  
  2559. - Headers can only be accessed when using `H'` instead of `'`.
  2560.  
  2561.  
  2562.  
  2563.  
  2564. ###############################################################
  2565. ###############################################################
  2566. Documentation of loaders for different systems
  2567. Implemtation specific notes
  2568. ###############################################################
  2569. ###############################################################
  2570.  
  2571.  
  2572. ###############################################################
  2573. Loader implementation for Atari ST
  2574. ###############################################################
  2575.  
  2576.  
  2577. The  author  of  F68K (that's me) is the proud owner of an Atari
  2578. ST.  So  the  loader  for this machine is the most sophisticated
  2579. until  now.  First  it was written in assembler and very simple,
  2580. taking  the  blocks directly from Disk. To give away any sources
  2581. meant  to  extract them from the disk and to put them into a DOS
  2582. file.
  2583.  
  2584. The  next  version  has been written with the very nice freeware
  2585. SOZOBON  C-compiler. This allows easy expansion of the loader in
  2586. the  future.  The  F68K blockdevices are totally emulated within
  2587. GEMDOS-files. A configuration file, which can be edited with any
  2588. texteditor,  is  supported now to make installation easy. I will
  2589. come to that later.
  2590.  
  2591. The  actual  version  was  build  using  the  commercial Turbo-C
  2592. compiler,  because  there  were to much bugs in the libraries of
  2593. the SOZOBON system.
  2594.  
  2595. The  SOZOBON  compiler  seemed to be made to write F68K loaders.
  2596. Only  a  very few lines of in-line assembler were enough to make
  2597. the  I/O  functions fit the the F68K parameter protocol. But the
  2598. source  was  not  portable because the in-line assembler is very
  2599. compiler  dependent. Using the Turbo-C compiler the in-line code
  2600. vanishes  completely.  But  one  has to use the compilerspecific
  2601. keyword  CDECL  for all I/O functions to achieve that parameters
  2602. are passed on the stack instead of passing them in registers.
  2603.  
  2604. The  configuration  file  contains the name of the system image,
  2605. the  sizes  for code and data segments, the names of the READSYS
  2606. inputfile  and the WRITESYS outputfile (see 'Loader') as well as
  2607. the  number  of  devices  and the names of the appropriate .SCR-
  2608. files.  Some errorchecking is done while interpreting this file,
  2609. but  the  user  should  try  to keep it clean, nevertheless. The
  2610. order  of  the  entries in this file may not be changed (it's C,
  2611. not FORTH).
  2612.  
  2613.  
  2614.  
  2615.  
  2616.  Installation of F68K on Atari ST
  2617.  
  2618. F68K  for  Atari  ST will come completetly installed as a floppy
  2619. based  system.  This  is  not  very  fast,  especially using the
  2620. blockstream  system, but there is no reason not to install it on
  2621. a  hard- or ramdisk. Therefore a hard- or ramdisk must exist, of
  2622. course.   When   putting   the   source  to  another  device,  a
  2623. recompilation of F68K can be usefull, when the order or the size
  2624. of  the  logical F68K devices, that means the GEMDOS files, have
  2625. changed.  Otherwise  just  a  copy  of  one  or all files to the
  2626. desired  place  and  changes to the corresponding entries in the
  2627. F68K  configuration  file  F68K.CFG have to be made. If the user
  2628. wants to duplicate one file on a hard- or ramdisk, that means to
  2629. hold the same file on floppydisk and on e.g. harddisk, he has to
  2630. take  care  about  the filesystem. It has to be UNMOUNTed before
  2631. copying.  After  the copy completed and the necessary changes in
  2632. the  configuration  file  have  been  performed,  both  new F68K
  2633. devices  will  have  to  MOUNTed  again.  That's  all. VIEW will
  2634. nevertheless  search  his information on the original device! To
  2635. alter this, the user will have to recompile the system.
  2636.  
  2637. Recompiling goes in two steps. It is possible to make the second
  2638. one only. First the filesystem itself has to be loaded on top of
  2639. the kernel. Therefore the name of the image in the configuration
  2640. file has to be changed into KERNEL.IMG. The filesystem's sources
  2641. are  located  in  the  file  RAW.SCR, which indicates, that this
  2642. device cannot be accessed via the blockstream system. If RAW.SCR
  2643. is the first device in the configuration file, the system can be
  2644. started  and  '1  LOAD' can be performed. If it is not, the user
  2645. has to get the rootblock of the device from the ROOTTABLE and to
  2646. store  it in the USER-variable ROOTBLK, e.g. if it is the second
  2647. (counted from 0) device
  2648.  
  2649.  
  2650. 2 8* ROOTTABLE + 4+ @  ROOTBLK !
  2651.  
  2652.  
  2653. Then again, '1 LOAD'.
  2654.  
  2655.  
  2656. When  loading  finishes  the  new image can be saved using SAVE.
  2657. This  image  now  is  a  GEMDOS  file with the name given in the
  2658. configuration file behind 'output:'. This will be the new kernel
  2659. in future.
  2660.  
  2661. The user leaves F68K, changes the configuration file in order to
  2662. use  the  new  image  and  starts  F68K  again.  It will use the
  2663. blockstream system from now on.
  2664.  
  2665. In  the  second step, the system extensions can be loaded. After
  2666. changing to the appropriate device and saying 'MOUNT' for safety
  2667. the user may change to the directory SYSTEM via
  2668.  
  2669.  
  2670. CD SYSTEM
  2671.  
  2672.  
  2673. There  will  be  a blockstream called LOADME which can be loaded
  2674. with
  2675.  
  2676.  
  2677. USE LOADME
  2678. 1 LOAD
  2679.  
  2680.  
  2681. After   the   (hopefully)  succesful  completion,  SAVE  can  be
  2682. performed again (the user has to make sure that the former saved
  2683. image is not overwritten now!).
  2684.  
  2685. After  that the system is installed completely and ready to use.
  2686. VIEW  will  search  on the logical devices where source has been
  2687. compiled from.
  2688.  
  2689.  
  2690.  
  2691.  
  2692.  
  2693. ###############################################################
  2694. Loader implementation for Sinclair QL
  2695. ###############################################################
  2696.  
  2697.  
  2698.  
  2699. **************************************************
  2700. ***                                            ***
  2701. ***                Loader for                  ***
  2702. ***                ^^^^^^^^^^                  ***
  2703. ***                   F68K                     ***
  2704. ***                   ^^^^                     ***
  2705. ***                  on the                    ***
  2706. ***                Sinclair QL                 ***
  2707. ***                                            ***
  2708. ***              by Dirk Kutscher              ***
  2709. ***                                            ***
  2710. **************************************************
  2711.  
  2712. Content
  2713.          Hardware Requirements
  2714.          Files
  2715.          Getting started
  2716.          Special features
  2717.          Problems?
  2718.          Remark
  2719.  
  2720.  
  2721. *************************
  2722. * Hardware Requirements *
  2723. *************************
  2724.  
  2725. To  start  F68K on your QL you need at least one 3.5" disc drive
  2726. and  a  minimum  of  256  KB RAM. If you lack the disc drive you
  2727. might  be  able  to  run  F68K  but  should  not  try to use the
  2728. Streaminterface  to  access  DEVICE1_SCR  since it is assumed to
  2729. provide  300 blocks which you cannot emulate on microdrive. I am
  2730. working at a mdv version at the moment.
  2731.  
  2732.  
  2733. ************
  2734. *  FILES   *
  2735. ************
  2736.  
  2737. The loader consists of the following files:
  2738.  
  2739. bootF68K_QL
  2740.  
  2741. This is a SuperBASIC-program which initialises the F68K-Disc for
  2742. the  use on a QL-System. If your F68K version was distributed on
  2743. Atari  Disc  it is necessary to recreate the QLF68K_exe file (as
  2744. well as QLCONFIG_exe) since the job information in the header of
  2745. QL-files  (Dataspace etc.) is not available on Atari Discs. Once
  2746. you have run this program on your QL Disc you can happily forget
  2747. it.
  2748.  
  2749.  
  2750. QLF68K_EXE
  2751.  
  2752. This the EXECutable loader created by boot. Start F68K by typing
  2753. 'EXEC flp1_QLF68K_EXE'. Of course you can also use QRAM etc..
  2754.  
  2755.  
  2756. QLF68K_CDE
  2757.  
  2758. This  is  the  machinecode program for loading F68K. If you have
  2759. the -exe file installed it should not concern you anymore.
  2760.  
  2761.  
  2762. QLF68K_ASM
  2763.  
  2764. This  is  the  assembler source for the loader. It will probably
  2765. only assemble on Talent's Workbench Assembler, but it might give
  2766. you  some ideas of how to write your own loaders. (Of course you
  2767. may also use it to expand the loader).
  2768.  
  2769.  
  2770. QLF68K_TXT    this one
  2771.  
  2772.  
  2773. CHANGES_TXT   loader development documentation
  2774.  
  2775.  
  2776. QLCONFIG_exe
  2777.  
  2778. This  is  the configuration utility for QLF68K_exe. It gives you
  2779. the  possiblity  to  patch  the following filenames according to
  2780. your personal hardware environment:
  2781.  
  2782.             flp1_F68K_img       (the F68K bit image)
  2783.             flp1_F68K_out       (the F68K output file)
  2784.             flp1_F68K_in        (the F68K input file)
  2785.             flp1_DEVICE1_scr    (Blockdevice for RW-access)
  2786.             flp1_STREAMS_scr              ""
  2787.             ser1                (Printer device)
  2788.  
  2789. If  you  like  to  keep  these names you just have to confirm by
  2790. hitting ENTER. You are then asked (in German), if you would like
  2791. these names (except for the printer) to be questioned again when
  2792. starting  F68K. For experiments, first attempts etc. it might be
  2793. useful  to  answer  'j' (for 'yes'). If you are familar with the
  2794. system  or  even want save a complete application 'n' (for 'No')
  2795. will make the loader start F68K directly when executed.
  2796.  
  2797.  
  2798. QLCONFIG_cde
  2799.  
  2800. The   mc-file   for   the   configuration   utility.  Loaded  by
  2801. bootF68K_QL.
  2802.  
  2803.  
  2804.  
  2805. *******************
  2806. * Getting started *
  2807. *******************
  2808.  
  2809. On  executing  QLF68K_exe  the  program  first tries to allocate
  2810. enough space in the memory for F68K. If the neccessary amount of
  2811. bytes  ($10000  + $20028 for code and data) is not available the
  2812. execution will terminate.
  2813.  
  2814. After  this  the  program  opens  the  console and gives you the
  2815. possibility  to  change  the names for the necessary files. (See
  2816. files.QLConfig_exe) If you do change the names (e.g. the device)
  2817. you should make sure that these files really exist and that they
  2818. also can be accessed in the same way as the original file names.
  2819. If no change is necessary just confirm by hitting ENTER.
  2820.  
  2821. Now  the program is loading the F68K-file (i.e 'flp1_F68K_IMG').
  2822. If  loading  has  been succesful F68K should now prompt with the
  2823. copyright note and with it's 'ok'.
  2824.  
  2825. If  you  want to access the Blockdevice now you should make sure
  2826. that  you  can provide the specified files (e.g. DEVICE1_SCR and
  2827. STREAMS_SCR)  on  the  specified  devices otherwise you might at
  2828. least  get  an  error report by QDOS or F68K. You do not have to
  2829. worry  about  closing  channels  when  changing discs (e.g. on a
  2830. multitasking QL), since the RW routines are somewhat 'atomic' in
  2831. this  regard:  They open and close their channels each time they
  2832. are  called. At first this seems to slow down the block accesses
  2833. but  thanks  to  QDOS  this  impression vanishes because all the
  2834. often called directory blocks etc. are stored in slave blocks of
  2835. the QDOS filing system.
  2836.  
  2837.  
  2838.  
  2839. ********************
  2840. * Special features *
  2841. ********************
  2842.  
  2843. Since  F68K's  editor  uses VT52-sequences to control the cursor
  2844. etc.,  which  is  normally non-standard on the QL, these control
  2845. codes are emulated by the loader's I/O routines. There is also a
  2846. translation   table   for  some  special  characters  ("Deutsche
  2847. Umlaute") including ENTER, BACKSPACE etc.
  2848.  
  2849. Nevertheless  the  user  may still redirect I/O as he desires. I
  2850. have  provided  three  different  EMIT  routines  each  giving a
  2851. different  degree  of  emulation: Default is full emulation. The
  2852. VT52-sequences  as  well  as  the  the  translation  tables  are
  2853. supported.  You  could  switch  between these different modes by
  2854. some simple FORTH words:
  2855.  
  2856.  
  2857.               : VT52_OFF ( -- ) EMITS 8 + @ ^EMIT ! ;
  2858.  
  2859.               : VT52_ON  ( -- ) EMITS 4 + @ ^EMIT ! ;
  2860.  
  2861.               : NO_TRANSLATION ( -- ) EMITS 12 + @ ^EMIT ! ;
  2862.  
  2863.  
  2864.  
  2865.  
  2866. *************
  2867. * Problems? *
  2868. *************
  2869.  
  2870. Problems  may  occur if you have got the TOS-formatted F68K disc
  2871. and  are  not  able  to create the appropriate QL disc, probably
  2872. because  you  lack a disc driver or a transformation utility. In
  2873. such  a  case  you can send me (adress below) two QDOS-formatted
  2874. 3.5" discs AND a paid and self-adressed envelope and I will rush
  2875. you the latest QL version as soon as possible.
  2876.  
  2877.  
  2878.  
  2879. **********
  2880. * Remark *
  2881. **********
  2882.  
  2883. I  have  written  this  loader to support both the spread of the
  2884. programming language Forth and QDOS, the operating system of the
  2885. QL. So you can make as many copies of the loader as you want and
  2886. also  distribute  them  as  long  as  no profit is gained by the
  2887. distribution.  I  would  also  like  my  name to be kept visible
  2888. etc...
  2889.  
  2890. The  programme  has  been  successfully  tested on R. Kowallik's
  2891. QL-Emulator for the Amiga.
  2892.  
  2893. I  have  no  objections  to  somebody writing a C version of the
  2894. loader  nor  other improvements. I would be pleased to hear from
  2895. you then!
  2896.  
  2897. For  suggestions, questions or any other comments please use the
  2898. following adress:
  2899.  
  2900.          Dirk Kutscher
  2901.          Kastanienweg 39
  2902.          2804 Lilienthal
  2903.          Germany
  2904.  
  2905. You  can  also  contact  me via eMail using one of the following
  2906. adresses:
  2907.  
  2908. Dirk_Kutscher@HB.MAUS.DE
  2909.  
  2910. Karl @ BBS.FORTH-eV.de
  2911.  
  2912.  
  2913.  
  2914. ###############################################################
  2915. Loader implementation for Commodore Amiga
  2916. ###############################################################
  2917.  
  2918. The amiga support for the F68K consists of 4 files:
  2919.  
  2920. --- LOAD4TH         the loader
  2921. --- LOAD4TH.c       it's source
  2922. --- LOAD4TH.info    the logo to start it from the workbench
  2923. --- and this file.
  2924.  
  2925. In  general,  it's in functional agreement with the atari Loader
  2926. for  the  F68K,  especially  concerning the environment handling
  2927. with the configuration file F68K.CFG.
  2928.  
  2929. I added two little options to get screen data printed on paper:
  2930.  
  2931. ---  Starting  "LOAD4TH  p"  opens  the  file  "dump.dat" in the
  2932. current  directory  and  puts  all  bytes  into  it, that passed
  2933. through the "Emit" function.
  2934.  
  2935. ---  starting "LOAD4TH s" does the same with the exception, that
  2936. CR's  are  are filtered out, furthermore any byte that follows a
  2937. LF.  This  provides  a very simple and effective method to print
  2938. screens. (I like programming in bed, and because the amiga isn't
  2939. a  laptop..)  It  is  applied  to the F68K "list" word, and very
  2940. little extra work on a conventional editor is necessary to clean
  2941. out the rest of OS-garbage contained in the file.
  2942.  
  2943. Since  the  amiga  uses some special keycodes, three commands of
  2944. the fullscreen-editor had to be changed:
  2945.  
  2946.       ^F instead of ^? calls the help screen
  2947.       ^V instead of ^< does #1.load
  2948.       ^\ instead of ^> does load.exit
  2949.  
  2950. Despite  of  this, all operation is the same as described in the
  2951. F68K  original  documentation.  Before first use, the blockfiles
  2952. have  to  be "unmount"ed and "mount"ed again as described in the
  2953. technical manual.
  2954.  
  2955. To  start  F68K  from  the workbench, the ".info"-file has to be
  2956. copied into the same directory, where the loader is. It will put
  2957. the  appropriate  logo  on the workbench. The p and s option are
  2958. available from the CLI only.
  2959.  If  you  have  received  these  files not on an amiga-formatted
  2960. disk,  the  file  "LOAD4TH.info"  might  have  been  renamed  as
  2961. "LOAD4TH.inf" to be in line with naming rules. When transferring
  2962. this  file  to  the amiga, it must be renamed to "LOAD4TH.info",
  2963. otherwise your workbench will not show it.
  2964.  
  2965. There  is  (at  the  present  state  of  development)  one major
  2966. problem, which should not be disregarded:
  2967.  
  2968. This  loader  opens  a  RAW: window on the amiga, which is quite
  2969. easy  to  program,  but  has  a fixed line resolution of 77 true
  2970. characters  per  row.  (There  is  a horizontal resolution of 80
  2971. Characters  of  this  standard  font,  but  two are lost for the
  2972. borderlines and one is reserved to place the leading cursor). If
  2973. anybody  knows a simple trick to smash this on DOS-level, let me
  2974. hear.
  2975.  
  2976. Questions and hints:
  2977.  
  2978.                        Wolfgang Schemmert
  2979.                          Luisenstr. 51
  2980.                         W-6050 Offenbach
  2981.                        Tel. 069-88 56 06
  2982.                        FAX  069-81 10 50
  2983.  
  2984.  
  2985.  
  2986.  
  2987.  
  2988. ###############################################################
  2989. Glossary
  2990. ###############################################################
  2991.  
  2992.  
  2993. (ABS) ( absaddr -- reladdr )
  2994.  
  2995. Vocabulary FORTH
  2996.  
  2997. Converts an absolute address into a standard F68K-datapointer.
  2998.  
  2999. Example:
  3000. 0 (ABS) @
  3001. \ gives the boot SSP
  3002.  
  3003.  
  3004.  
  3005.  
  3006. (ABSCODE) ( absaddr -- code-reladdr )
  3007.  
  3008. Vocabulary FORTH
  3009.  
  3010. Converts an absolute address into a standard F68K-datapointer.
  3011.  
  3012. Example:
  3013. 0 (ABSCODE) CODE>DATA @
  3014. \ gives the boot-SSP.
  3015.  
  3016.  
  3017.  
  3018.  
  3019. (EMIT) ( -- addr )
  3020.  
  3021. Vocabulary FORTH
  3022.  
  3023. (EMIT) is a USER-Variable, which contains an F68K pointer to
  3024. the word, which is executed by EMIT. It is preset with
  3025. LOADEREMIT.
  3026.  
  3027.  
  3028.  
  3029.  
  3030.  
  3031. (EXPECT) ( -- adr )
  3032.  
  3033. Vocabulary FORTH
  3034.  
  3035. (EXPECT) is a USER-variable which contains the CFA of the word
  3036. which will be used by EXEPCT.
  3037.  
  3038.  
  3039.  
  3040.  
  3041.  
  3042. (FIND ( string -- controlword cfa | string -1 )
  3043.  
  3044. Vocabulary FORTH
  3045.  
  3046. Searches for a word with the name given with the string in the
  3047. vocabularies found in the search order. (FIND uses VOCSEARCH.
  3048.  
  3049. Example:
  3050. " DUP" (find
  3051. \ or
  3052. ' (find Is find
  3053. " DUP" find
  3054.  
  3055.  
  3056.  
  3057.  
  3058. (KEY) ( -- addr )
  3059.  
  3060. Vocabulary FORTH
  3061.  
  3062. (KEY) is a USER-Variable, which contains an F68K pointer to the
  3063. word, which is executed by KEY. It is preset with LOADERKEY.
  3064.  
  3065.  
  3066.  
  3067.  
  3068.  
  3069. (KEY?) ( -- addr )
  3070.  
  3071. Vocabulary FORTH
  3072.  
  3073. (KEY?) is a USER-Variable, which contains an F68K pointer to
  3074. the word, which is executed by KEY?. It is preset with
  3075. LOADERKEY?.
  3076.  
  3077.  
  3078.  
  3079.  
  3080.  
  3081. (R/W) ( -- addr )
  3082.  
  3083. Vocabulary FORTH
  3084.  
  3085. (R/W) is a USER-Variable, which contains an F68K pointer to the
  3086. word, which is executed by R/W. It is preset with LOADERR/W.
  3087.  
  3088.  
  3089.  
  3090.  
  3091.  
  3092. (READSYS) ( -- addr )
  3093.  
  3094. Vocabulary FORTH
  3095.  
  3096. (READSYS) is a USER-Variable, which contains an F68K pointer to
  3097. the word, which is executed by READSYS. It is preset with
  3098. LOADERREADSYS.
  3099.  
  3100.  
  3101.  
  3102.  
  3103.  
  3104. (TYPE) ( -- adr )
  3105.  
  3106. Vocabulary FORTH
  3107.  
  3108. (TYPE) is a USER-variable which contains the CFA of the word
  3109. which will be used by TYPE.
  3110.  
  3111.  
  3112.  
  3113.  
  3114.  
  3115. (WRITESYS) ( -- addr )
  3116.  
  3117. Vocabulary FORTH
  3118.  
  3119. (WRITESYS) is a USER-Variable, which contains an F68K pointer
  3120. to the word, which is executed by WRITESYS. It is preset with
  3121. LOADERWRITESYS.
  3122.  
  3123.  
  3124.  
  3125.  
  3126.  
  3127. .LAST ( -- )
  3128.  
  3129. Vocabulary FORTH
  3130.  
  3131. Prints the name of the most recently defined word.
  3132.  
  3133.  
  3134.  
  3135.  
  3136.  
  3137. >ABS ( reladdr -- absaddr )
  3138.  
  3139. Vocabulary FORTH
  3140.  
  3141. Converts a standard F68K-datapointer into an absolute address.
  3142.  
  3143. Example:
  3144. 0 >ABS
  3145. \ gives the physical start of datasegement
  3146.  
  3147.  
  3148.  
  3149.  
  3150. >ABSCODE ( code-reladdr -- absaddr )
  3151.  
  3152. Vocabulary FORTH
  3153.  
  3154. Converts a standard F68K-codepointer into an absolute address.
  3155.  
  3156. Example:
  3157. 0 >ABSCODE
  3158. \ gives the physical start of codesegement
  3159.  
  3160.  
  3161.  
  3162.  
  3163. >R ( n -- )
  3164.  
  3165. Vocabulary FORTH
  3166.  
  3167. Pushes the top of stack onto the returnstack. A conversion is
  3168. done so that a standard F68K-codepointer becomes an absolute
  3169. machineaddress on the returnstack. 'R>' and 'R@' reconvert the
  3170. value on the returnstack so that conversion should be invisible
  3171. to the user.
  3172.  
  3173.  
  3174.  
  3175.  
  3176.  
  3177. ?CR ( column -- )
  3178.  
  3179. Vocabulary FORTH
  3180.  
  3181. If the actual writing column (held in OUT) is greater than the
  3182. given column, a CR is performed.
  3183.  
  3184.  
  3185.  
  3186.  
  3187.  
  3188. [VOC'] ( -- ) \ : ... [voc'] <vocname> ... ;
  3189.  
  3190. Vocabulary FORTH
  3191.  
  3192. Finds the address of the named vocabulary. This may be very
  3193. usefull together with searching word VOCSEARCH. The returned
  3194. address corresponds to those held in CURRENT or CONTEXT. This
  3195. is the compiletime version of VOC'.
  3196.  
  3197. Example:
  3198. : findDUP
  3199.     " DUP" [voc'] forth vocsearch ;
  3200. \ see also VOC'
  3201.  
  3202.  
  3203.  
  3204.  
  3205. ^EMIT ( -- addr )
  3206.  
  3207. Vocabulary FORTH
  3208.  
  3209. ^EMIT is a vector which contains the function which is actually
  3210. used to emit a character. Normally, I would have named such a
  3211. vector (EMIT), but in this case the content of ^ EMIT is not
  3212. executable by EXECUTE, for it needs somw interfacing provided
  3213. by EMIT, which calls the function ^EMIT points to.
  3214.  
  3215.  
  3216.  
  3217.  
  3218.  
  3219. ^KEY ( -- addr )
  3220.  
  3221. Vocabulary FORTH
  3222.  
  3223. ^KEY is a vector which contains the function which is actually
  3224. used to get a character from the terminal (or from elsewhere).
  3225. See ^EMIT!
  3226.  
  3227.  
  3228.  
  3229.  
  3230.  
  3231. ^KEY? ( -- addr )
  3232.  
  3233. Vocabulary FORTH
  3234.  
  3235. ^KEY? is a vector which contains the function which is actually
  3236. used to check the state of the terminal. See ^EMIT!
  3237.  
  3238.  
  3239.  
  3240.  
  3241.  
  3242. ^R/W ( -- addr )
  3243.  
  3244. Vocabulary FORTH
  3245.  
  3246. ^R/W is a vector which contains the function which is actually
  3247. used to read or write from/to mass storage. See ^EMIT!
  3248.  
  3249.  
  3250.  
  3251.  
  3252.  
  3253. ^READSYS ( -- addr )
  3254.  
  3255. Vocabulary FORTH
  3256.  
  3257. ^READSYS is a vector which contains the function which is
  3258. actually used to read a file in a system dependent manner. See
  3259. ^EMIT!
  3260.  
  3261.  
  3262.  
  3263.  
  3264.  
  3265. ^WRITESYS ( -- addr )
  3266.  
  3267. Vocabulary FORTH
  3268.  
  3269. ^WRITESYS is a vector which contains the function which is
  3270. actually used to write a file in a system dependent manner. See
  3271. ^EMIT!
  3272.  
  3273.  
  3274.  
  3275.  
  3276.  
  3277. ALSO ( -- )
  3278.  
  3279. Vocabulary ONLY
  3280.  
  3281. ALSO is a 'DUP' on vocabulary-stack. The first vocabulary in
  3282. the search order is searched twice after ALSO. In most cases,
  3283. this first vocabulary will be replaced by an other one.
  3284.  
  3285. Example:
  3286. FLOAT ALSO FORTH
  3287. \ The use of 'ALSO' is reverse to 'TOSS'.
  3288.  
  3289.  
  3290.  
  3291.  
  3292. BACKSPACE ( -- )
  3293.  
  3294. Vocabulary FORTH
  3295.  
  3296. Emits the ASCII-Code 8 in order to move the cursor one column
  3297. to left.
  3298.  
  3299. Example:
  3300. : backspace ( -- ) 8 emit ;
  3301.  
  3302.  
  3303.  
  3304.  
  3305. BACKSPACES ( n -- )
  3306.  
  3307. Vocabulary FORTH
  3308.  
  3309. Executes BACKSPACE in a loop.
  3310.  
  3311.  
  3312.  
  3313.  
  3314.  
  3315. BCREATE ( name length -- flag )
  3316.  
  3317. Vocabulary BLOCKSTREAM
  3318.  
  3319. Creates a blockstream with the given length. The name has to be
  3320. a counted string. The returned flag is 0 when successful. The
  3321. flag has value <>0 for different reasons, that cannot be seen
  3322. from the flag. Errorconditions are a lack of diskspace or the
  3323. stream to be created already exists.
  3324.  
  3325.  
  3326.  
  3327.  
  3328.  
  3329. BDELETE ( name -- flag )
  3330.  
  3331. Vocabulary BLOCKSTREAM
  3332.  
  3333. Deletes a blockstream from the directory. The name has to be a
  3334. counted string. The flag is 0 when successful. An
  3335. errorcondition exists when the stream does not exist. The user
  3336. has to take care that no stream-structure connected with the
  3337. deleted stream will be used after deletion. (be VERY careful!)
  3338.  
  3339.  
  3340.  
  3341.  
  3342.  
  3343. BELL ( -- )
  3344.  
  3345. Vocabulary FORTH
  3346.  
  3347. Writes '7' to the terminal which should respond with noise.
  3348.  
  3349. Example:
  3350. : bell ( -- ) 7 emit ;
  3351.  
  3352.  
  3353.  
  3354.  
  3355. BLK ( -- addr )
  3356.  
  3357. Vocabulary FORTH
  3358.  
  3359. BLK is a USER-variable, which contains the number of the
  3360. physical block actually loaded.
  3361.  
  3362.  
  3363.  
  3364.  
  3365.  
  3366. BYE ( ?? -- )
  3367.  
  3368. Vocabulary FORTH
  3369.  
  3370. Leaves the F68K interpreter and gives control back to the
  3371. loader.
  3372.  
  3373.  
  3374.  
  3375.  
  3376.  
  3377. CAPACITY ( -- n )
  3378.  
  3379. Vocabulary FORTH
  3380.  
  3381. Gives the length of the current blockstream.
  3382.  
  3383. Example:
  3384. 1 capacity index
  3385. \ INDEX for the whole blockstream
  3386.  
  3387.  
  3388.  
  3389.  
  3390. CAPS ( -- addr )
  3391.  
  3392. Vocabulary FORTH
  3393.  
  3394. This USER-variable decides wether strings isolated from the
  3395. inputstream are capitalized. This can be very useful when
  3396. 'misusing' the interpreter.
  3397.  
  3398.  
  3399.  
  3400.  
  3401.  
  3402. CD ( -- ) \ CD <name> or CD
  3403.  
  3404. Vocabulary FORTH
  3405.  
  3406. This will change to the directory given in <name>. If no <name>
  3407. is given, then the actual directory path is printed on the
  3408. terminal.
  3409.  
  3410.  
  3411.  
  3412.  
  3413.  
  3414. CELL+ ( n -- n+4 )
  3415.  
  3416. Vocabulary FORTH
  3417.  
  3418. Increases n by the width of one addresscell = 4 bytes.
  3419.  
  3420.  
  3421.  
  3422.  
  3423.  
  3424. CELL- ( n -- n-4 )
  3425.  
  3426. Vocabulary FORTH
  3427.  
  3428. Decreases n by the width of one addresscell = 4 bytes.
  3429.  
  3430.  
  3431.  
  3432.  
  3433.  
  3434. CELLS ( n -- n*4 )
  3435.  
  3436. Vocabulary FORTH
  3437.  
  3438. Calculates the width of n addresscells.
  3439.  
  3440. Example:
  3441. CREATE FIELD
  3442.     0 , 1 , 2 , 3 , 4 , 5 ,
  3443. : 3 ( -- 3 )
  3444.     FIELD 3 CELLS + @ ;
  3445.  
  3446.  
  3447.  
  3448.  
  3449. CHANGEDIR ( name -- flag )
  3450.  
  3451. Vocabulary BLOCKSTREAM
  3452.  
  3453. Changes to the given directory. The name has to be a counted
  3454. string. The flag is 0 when successful. Changing a directory
  3455. means to put the physical number of the directory block into
  3456. the USER- variable DIRECTORY. An errorcondition exists when the
  3457. given directory does not exist.
  3458.  
  3459.  
  3460.  
  3461.  
  3462.  
  3463. CHAR+ ( addr -- addr+1 )
  3464.  
  3465. Vocabulary FORTH
  3466.  
  3467. Calculates the address of the following character.
  3468.  
  3469.  
  3470.  
  3471.  
  3472.  
  3473. CHARS ( n -- n )
  3474.  
  3475. Vocabulary FORTH
  3476.  
  3477. Calculates the address distance of <n> characters. In F68K,
  3478. CHARS is a dummy, because the length of a character is 1.
  3479.  
  3480.  
  3481.  
  3482.  
  3483.  
  3484. CODE! ( n coderelative-addr -- )
  3485.  
  3486. Vocabulary FORTH
  3487.  
  3488. Stores a value into the codesegment. See CODE@ and CODE>DATA.
  3489.  
  3490. Example:
  3491. : CODE!   CODE>DATA ! ;
  3492.  
  3493.  
  3494.  
  3495.  
  3496. CODE>DATA ( coderelative-addr -- datarelative-addr )
  3497.  
  3498. Vocabulary FORTH
  3499.  
  3500. Converts an address, which is relative to the codesegment, into
  3501. an address relative to the datasegment.
  3502.  
  3503.  
  3504.  
  3505.  
  3506.  
  3507. CODE@ ( coderelative-addr -- n )
  3508.  
  3509. Vocabulary FORTH
  3510.  
  3511. Fetches a value from the codesegment, e.g. '-addresses. See
  3512. CODE! and CODE>DATA.
  3513.  
  3514. Example:
  3515. : CODE@   CODE>DATA @ ;
  3516. ' PARSER CELL+ CODE@ @
  3517. \ get the pointer to the runtime routine
  3518. \ of the DEFERed PARSER
  3519. \ = ' INTERPRETER or ' COMPILER
  3520.  
  3521.  
  3522.  
  3523.  
  3524. COLUMNS ( -- addr )
  3525.  
  3526. Vocabulary FORTH
  3527.  
  3528. Variable which holds the number of available columns on the
  3529. current terminal.
  3530.  
  3531.  
  3532.  
  3533.  
  3534.  
  3535. COMPILER ( addr -- )
  3536.  
  3537. Vocabulary FORTH
  3538.  
  3539. COMPILER tries to compile the input stream. It is used by
  3540. INTERPRET when STATE <>0.
  3541.  
  3542.  
  3543.  
  3544.  
  3545.  
  3546. DCREATE ( name -- flag )
  3547.  
  3548. Vocabulary BLOCKSTREAM
  3549.  
  3550. Creates a subdirectory. The name has to be a counted string.
  3551. The flag is 0 when successful. An errorcondition exists when
  3552. there is not enough diskspace to create the directory, which
  3553. needs at least one block.
  3554.  
  3555.  
  3556.  
  3557.  
  3558.  
  3559. DDELETE ( name -- flag )
  3560.  
  3561. Vocabulary BLOCKSTREAM
  3562.  
  3563. Deletes a directory. The name has to be a counted string. The
  3564. flag is 0 when successful. An errorcondition exists when the
  3565. directory does not exist.
  3566.  
  3567.  
  3568.  
  3569.  
  3570.  
  3571. DEL ( -- ) \ DEL <name>
  3572.  
  3573. Vocabulary FORTH
  3574.  
  3575. This will delete the blockstream with the given name. If the
  3576. stream has former been USEd, the F68K word created there will
  3577. not be deleted!
  3578.  
  3579.  
  3580.  
  3581.  
  3582.  
  3583. DELDIR ( -- ) \ DELDIR <name>
  3584.  
  3585. Vocabulary FORTH
  3586.  
  3587. This will delete a directory. Notice that this directory has to
  3588. be empty, e.g. it may contain nor streams neither directories,
  3589. otherwise an error condition exists.
  3590.  
  3591.  
  3592.  
  3593.  
  3594.  
  3595. DIR ( -- )
  3596.  
  3597. Vocabulary FORTH
  3598.  
  3599. Shows the content of the current directory.
  3600.  
  3601.  
  3602.  
  3603.  
  3604.  
  3605. DIRECT ( -- )
  3606.  
  3607. Vocabulary FORTH
  3608.  
  3609. Switches the blockstreamsystem of. Now BLOCK, LOAD and BUFFER
  3610. access the physical blocks again. The variable ROOTBLK is
  3611. deleted.
  3612.  
  3613.  
  3614.  
  3615.  
  3616.  
  3617. DROP ( n -- )
  3618.  
  3619. Vocabulary FORTH
  3620.  
  3621. DROPs the top element on stack (TOS).
  3622.  
  3623.  
  3624.  
  3625.  
  3626.  
  3627. DUP ( n -- n n )
  3628.  
  3629. Vocabulary FORTH
  3630.  
  3631. DUPlicates the top of stack (TOS).
  3632.  
  3633.  
  3634.  
  3635.  
  3636.  
  3637. EMIT ( character -- )
  3638.  
  3639. Vocabulary FORTH
  3640.  
  3641. Writes the character on the stack to the terminal. EMIT uses
  3642. the function stored in the USER-variable ^EMIT. This function
  3643. must use one of the loaders I/O-routines, which are stored in
  3644. the array EMITS, because some interfacing has to be done with
  3645. these routines.
  3646.  
  3647.  
  3648.  
  3649.  
  3650.  
  3651. EMITS ( -- addr )
  3652.  
  3653. Vocabulary FORTH
  3654.  
  3655. Gives the address of an array, which holds the number and the
  3656. entry-addresses of the loaders I/O-functions to emit a
  3657. character to the terminal. 'EMITS @' gives the number of the
  3658. functions. 'EMITS 4+ @' is the address of the first routine.
  3659. The routines in this table may not be executed from F68K
  3660. because they need some interfacing provided by EMIT.
  3661.  
  3662.  
  3663.  
  3664.  
  3665.  
  3666. EVALUATE ( c-addr count -- )
  3667.  
  3668. Vocabulary FORTH
  3669.  
  3670. This is an explicite call of the outer interpreter. The string
  3671. at c-addr with the length count is interpreted. EVALUATE may be
  3672. nested.
  3673.  
  3674. Example:
  3675. " 1 2 3 . . . " EVALUATE
  3676. \ gives: 3 2 1
  3677.  
  3678.  
  3679.  
  3680.  
  3681. EXPEL ( where amount -- )
  3682.  
  3683. Vocabulary BLOCKSTREAM
  3684.  
  3685. This will cut <amount> blocks out of the current blockstream.
  3686. The block <where> will not be cut, it remains in the stream. To
  3687. remember this, remember that the first block of a stream cannot
  3688. be EXPELled.
  3689.  
  3690. Example:
  3691. 3 2 EXPEL
  3692. \ will cut the block 4 and 5
  3693. \ from the stream
  3694.  
  3695.  
  3696.  
  3697.  
  3698. FIND ( string -- controlword cfa | string -1 )
  3699.  
  3700. Vocabulary FORTH
  3701.  
  3702. Searches for a word with the name given with the string in the
  3703. vocabularies found in the search order. FIND is a deferred word
  3704. and initially executes (FIND.
  3705.  
  3706. Example:
  3707. " DUP" find
  3708. \ using kernel's FIND:
  3709. ' (find Is find
  3710.  
  3711.  
  3712.  
  3713.  
  3714. FORTHPARAS ( -- addr )
  3715.  
  3716. Vocabulary FORTH
  3717.  
  3718. Gives a pointer to a structure which is provided by the loader
  3719. and holds all parameters the loader passes to F68K. F68K itself
  3720. will store the loaders registers here in order to give the
  3721. loader access to its own runtime environment. The FORTHPARAS
  3722. are of following structure:
  3723.  
  3724. Example:
  3725. struct forthparas
  3726. {
  3727.     long registers[16];
  3728.     /* to be filled by F68K */
  3729.     void *data, *code;
  3730.     void *datstk; *retstk;
  3731.     void *TIBptr;
  3732.     void *keytable;
  3733.     void *keyqtable;
  3734.     void *r_wtable;
  3735.     void *readsystable;
  3736.     void *writesystable;
  3737.     void *roottable;
  3738. }forthparas;
  3739.  
  3740.  
  3741.  
  3742.  
  3743. INCLUDE ( -- ) \ INCLUDE <filename>
  3744.  
  3745. Vocabulary FORTH
  3746.  
  3747. This is an interactive word to 'USE 1 LOAD' a blockstream. This
  3748. is usefull, because it is not allowed to 'USE 1 LOAD' streams
  3749. from within other USEd streams. USEing a stream while loading
  3750. another USEd streams implies to make the new stream the actual
  3751. one. So there is no return! INCLUDE saves the actual stream and
  3752. restores it again (see SAVE_STREAM, RESTORE_STREAM).
  3753.  
  3754.  
  3755.  
  3756.  
  3757.  
  3758. INDEX ( fromblock toblock -- )
  3759.  
  3760. Vocabulary FORTH
  3761.  
  3762. Gives a list of the first lines in the specified range of
  3763. blocks. There is a convention that the first line in each
  3764. screen has to be a comment.
  3765.  
  3766. Example:
  3767. 1 capacity index
  3768. \ INDEX for the whole blockstream
  3769.  
  3770.  
  3771.  
  3772.  
  3773. INSERT ( where amount -- )
  3774.  
  3775. Vocabulary FORTH
  3776.  
  3777. This will insert <amount> blocks at the position <where> in the
  3778. blockstream.
  3779.  
  3780.  
  3781.  
  3782.  
  3783.  
  3784. INTERPRET ( -- )
  3785.  
  3786. Vocabulary FORTH
  3787.  
  3788. This is the outer interpreter of the F68K-system. It will
  3789. expect some source code provided by SOURCE and interpret it
  3790. (surprising, isn't it?). It will return when the input stream
  3791. is exhausted, e.g. WORD gives back a NULLSTR?. INTERPRET
  3792. executes the DEFERed word PARSER to handle a string from the
  3793. source. PARSER holds either COMPILER or INTERPRETER.
  3794.  
  3795. Example:
  3796. : INTERPRET ( -- )
  3797.     BEGIN
  3798.         NAME NULLSTR?
  3799.     WHILE
  3800.         PARSER
  3801.     AGAIN ;
  3802.  
  3803.  
  3804.  
  3805.  
  3806. INTERPRETER ( addr -- )
  3807.  
  3808. Vocabulary FORTH
  3809.  
  3810. INTERPRETER tries to interpret the input stream provided by
  3811. SOURCE. It is used by INTERPRET when STATE=0.
  3812.  
  3813.  
  3814.  
  3815.  
  3816.  
  3817. KEY ( -- character )
  3818.  
  3819. Vocabulary FORTH
  3820.  
  3821. Reads a character from the terminal. KEY uses the function
  3822. stored in the USER-variable ^KEY. This function must use one of
  3823. the loaders I/O-routines, which are stored in the array KEYS,
  3824. because some interfacing has to be done with these routines.
  3825.  
  3826.  
  3827.  
  3828.  
  3829.  
  3830. KEY? ( -- flag )
  3831.  
  3832. Vocabulary FORTH
  3833.  
  3834. Checks the terminal for availability of a character. KEY? uses
  3835. the function stored in the USER-variable ^KEY?. This function
  3836. must use one of the loaders I/O-routines, which are stored in
  3837. the array KEY?S, because some interfacing has to be done with
  3838. these routines.
  3839.  
  3840.  
  3841.  
  3842.  
  3843.  
  3844. KEY?S ( -- addr )
  3845.  
  3846. Vocabulary FORTH
  3847.  
  3848. Gives the address of an array, which holds the number and the
  3849. entry-addresses of the loaders I/O-functions to check the state
  3850. of the terminal. 'KEY?S @' gives the number of the functions.
  3851. 'KEY?S 4+ @' is the address of the first routine. The routines
  3852. in this table may not be executed from F68K because they need
  3853. some interfacing provided by KEY?.
  3854.  
  3855.  
  3856.  
  3857.  
  3858.  
  3859. KEYS ( -- addr )
  3860.  
  3861. Vocabulary FORTH
  3862.  
  3863. Gives the address of an array, which holds the number and the
  3864. entry-addresses of the loaders I/O-functions to read a
  3865. character from the terminal. 'KEYS @' gives the number of the
  3866. functions. 'KEYS 4+ @' is the address of the first routine. The
  3867. routines in this table may not be executed from F68K because
  3868. they need some interfacing provided by KEY.
  3869.  
  3870.  
  3871.  
  3872.  
  3873.  
  3874. LASTBLK ( -- addr )
  3875.  
  3876. Vocabulary FORTH
  3877.  
  3878. This is a global variable, which holds the number of the
  3879. physical block last recently referred. Internally it is used to
  3880. access the actual blockbuffer very fast during LOAD together
  3881. with the content of LASTBUF. It may be very helpful while
  3882. debugging the blockstream system!
  3883.  
  3884.  
  3885.  
  3886.  
  3887.  
  3888. LASTBLOCK or LINKLAST ( physblk -- last-physblk )
  3889.  
  3890. Vocabulary BLOCKSTREAM
  3891.  
  3892. Same as NEXTBLOCK, but in the other direction. See notes there.
  3893.  
  3894.  
  3895.  
  3896.  
  3897.  
  3898. LASTBUF ( -- addr )
  3899.  
  3900. Vocabulary FORTH
  3901.  
  3902. This is a global variable, which holds the address of the
  3903. blockbuffer last recently used by BLOCK. Internally it is used
  3904. to access the actual blockbuffer very fast during LOAD together
  3905. with the content of LASTBLK. It may be very helpful while
  3906. debugging the blockstream system!
  3907.  
  3908.  
  3909.  
  3910.  
  3911.  
  3912. LESS ( n -- )
  3913.  
  3914. Vocabulary FORTH
  3915.  
  3916. This will reduce the blockstream currently in USE by n blocks.
  3917. They will be taken from the end of the stream.
  3918.  
  3919.  
  3920.  
  3921.  
  3922.  
  3923. LINKLAST ( block -- lastblock )
  3924.  
  3925. Vocabulary BLOCKSTREAM
  3926.  
  3927. Synonym for LASTBLOCK.
  3928.  
  3929.  
  3930.  
  3931.  
  3932.  
  3933. LINKNEXT ( block -- nextblock )
  3934.  
  3935. Vocabulary BLOCKSTREAM
  3936.  
  3937. Synonym for NEXTBLOCK.
  3938.  
  3939.  
  3940.  
  3941.  
  3942.  
  3943. LOAD ( blocknumber -- )
  3944.  
  3945. Vocabulary FORTH
  3946.  
  3947. Loads the block with the given number. During load, this number
  3948. is contained in the USER-variable BLK. BLK always contains the
  3949. physical blocknumber loaded!!
  3950.  
  3951.  
  3952.  
  3953.  
  3954.  
  3955. LOADEREMIT ( char -- )
  3956.  
  3957. Vocabulary FORTH
  3958.  
  3959. Executes the content of the USER-vector ^EMIT. Parameters are
  3960. converted from F68K to a standard C-format. So the content of
  3961. must not be executed using EXECUTE, but only by using
  3962. LOADEREMIT. ^EMIT can take one of the addresses held in the
  3963. array EMITS.
  3964.  
  3965.  
  3966.  
  3967.  
  3968.  
  3969. LOADERKEY ( -- char )
  3970.  
  3971. Vocabulary FORTH
  3972.  
  3973. Executes the content of the USER-vector ^KEY. Parameters are
  3974. converted from F68K to a standard C-format. So the content of
  3975. must not be executed using EXECUTE, but only by using
  3976. LOADERKEY. ^KEY can take one of the addresses held in the array
  3977. KEYS.
  3978.  
  3979.  
  3980.  
  3981.  
  3982.  
  3983. LOADERKEY? ( -- flag )
  3984.  
  3985. Vocabulary FORTH
  3986.  
  3987. Executes the content of the USER-vector ^KEY?. Parameters are
  3988. converted from F68K to a standard C-format. So the content of
  3989. must not be executed using EXECUTE, but only by using
  3990. LOADERKEY?. ^KEY? can take one of the addresses held in the
  3991. array KEYS?.
  3992.  
  3993.  
  3994.  
  3995.  
  3996.  
  3997. LOADERR/W ( buffer blocknumber r/w-flag -- )
  3998.  
  3999. Vocabulary FORTH
  4000.  
  4001. Executes the content of the USER-vector ^R/W. Parameters are
  4002. converted from F68K to a standard C-format. So the content of
  4003. must not be executed using EXECUTE, but only by using
  4004. LOADERR/W. ^R/W can take one of the addresses held in the array
  4005. R/WS.
  4006.  
  4007.  
  4008.  
  4009.  
  4010.  
  4011. LOADERREADSYS ( addr count -- flag )
  4012.  
  4013. Vocabulary FORTH
  4014.  
  4015. Executes the content of the USER-vector ^READSYS. Parameters
  4016. are converted from F68K to a standard C-format. So the content
  4017. of must not be executed using EXECUTE, but only by using
  4018. LOADERREADSYS. ^READSYS can take one of the addresses held in
  4019. the array READSYSES.
  4020.  
  4021.  
  4022.  
  4023.  
  4024.  
  4025. LOADERWRITESYS ( addr count -- flag )
  4026.  
  4027. Vocabulary FORTH
  4028.  
  4029. Executes the content of the USER-vector ^WRITESYS. Parameters
  4030. are converted from F68K to a standard C-format. So the content
  4031. of must not be executed using EXECUTE, but only by using
  4032. LOADERWRITESYS. ^WRITESYS can take one of the addresses held in
  4033. the array WRITESYSES.
  4034.  
  4035.  
  4036.  
  4037.  
  4038.  
  4039. LOCAL ( n -- ) \ <n> LOCAL <name>
  4040.  
  4041. Vocabulary FORTH
  4042.  
  4043. Creates a datatype similar to 'VALUE', but only within a
  4044. colon-definition. The memory for the data is allocated on the
  4045. returnstack.
  4046.  
  4047.  
  4048.  
  4049.  
  4050.  
  4051. MAKE ( -- ) \ MAKE <name>
  4052.  
  4053. Vocabulary FORTH
  4054.  
  4055. This will create a blockstream with length 1 in store it into
  4056. the actual directory or in the directory given together with
  4057. <name>.
  4058.  
  4059.  
  4060.  
  4061.  
  4062.  
  4063. MAKEDIR ( -- ) \ MAKEDIR <name>
  4064.  
  4065. Vocabulary FORTH
  4066.  
  4067. This will create a subdirectory with the given name.
  4068.  
  4069.  
  4070.  
  4071.  
  4072.  
  4073. MORE ( n -- )
  4074.  
  4075. Vocabulary FORTH
  4076.  
  4077. This will extend the blockstream which is currently in USE by n
  4078. further blocks. They will be appended to the end of the stream.
  4079.  
  4080.  
  4081.  
  4082.  
  4083.  
  4084. MOUNT ( -- )
  4085.  
  4086. Vocabulary FORTH
  4087.  
  4088. This will initialise a blockstream system copied to a device.
  4089. For directories contain physical blocknumbers, they are not
  4090. portable to other devices, where other blocknumbers are used.
  4091. MOUNT makes the blockstream system fit to the actual device.
  4092. Note that only a system, that has been UNMOUNTed, can be
  4093. mounted. Always make sure that you are working with MOUNTed
  4094. systems only. Oterhwise malfunction is guaranteed. It is not
  4095. possible to doubly MOUNT a system.
  4096.  
  4097.  
  4098.  
  4099.  
  4100.  
  4101. NEXTBLOCK or LINKNEXT ( physblk -- next-physblk )
  4102.  
  4103. Vocabulary BLOCKSTREAM
  4104.  
  4105. Get the link to the next physical blocknumber within a
  4106. blockstream. This is necessary when using systemvariables like
  4107. BLK. In former times one could ind the preceeding block by 'BLK
  4108. @ 1-'. These times are gone. Now it is 'BLK @LASTBLOCK'. Note
  4109. that the physical number is returned. Words like BLOCK, LOAD or
  4110. BUFFER may not be applied to that number. The words (BLOCK,
  4111. (LOAD and (BUFFER have to be used instead. The logical
  4112. blocknumber during LOAD is held in the USER-variable SBLK. The
  4113. user should be very careful not to mix up BLK and SBLK.
  4114.  
  4115.  
  4116.  
  4117.  
  4118.  
  4119. NIP ( a b -- b )
  4120.  
  4121. Vocabulary FORTH
  4122.  
  4123. Discards the second element on stack (SOS).
  4124.  
  4125.  
  4126.  
  4127.  
  4128.  
  4129. ORDER ( -- )
  4130.  
  4131. Vocabulary FORTH
  4132.  
  4133. Prints the actual search order.
  4134.  
  4135.  
  4136.  
  4137.  
  4138.  
  4139. OUT ( -- addr )
  4140.  
  4141. Vocabulary FORTH
  4142.  
  4143. USER-variable, which counts EMITs. It is reset by CR. OUT is
  4144. used to realize TABs or conditional CRs.
  4145.  
  4146.  
  4147.  
  4148.  
  4149.  
  4150. OVER ( a b -- a b a )
  4151.  
  4152. Vocabulary FORTH
  4153.  
  4154. Copies the second element on stack (SOS) to the top.
  4155.  
  4156.  
  4157.  
  4158.  
  4159.  
  4160. PUSH ( addr -- )
  4161.  
  4162. Vocabulary FORTH
  4163.  
  4164. Saves the content of addr on the returnstack. It will be
  4165. restored with the next 'EXIT' or ';' statement.
  4166.  
  4167. Example:
  4168. : hex.
  4169.     base push
  4170.     $10 base !
  4171.     . ;
  4172.  
  4173.  
  4174.  
  4175.  
  4176. QUIT ( ?? -- ?? )
  4177.  
  4178. Vocabulary FORTH
  4179.  
  4180. Invokes the outer F68K interpreter (for F68K is a native code
  4181. system, there is no inner interpreter at all). The returnstack
  4182. is reset and the datastack is tested for underflow.
  4183.  
  4184.  
  4185.  
  4186.  
  4187.  
  4188. R/W ( buffer blocknumber rwflag -- )
  4189.  
  4190. Vocabulary FORTH
  4191.  
  4192. Writes or reads 2048 bytes from/to the buffer from/to the block
  4193. with the given number on the mass storage device. R/W uses the
  4194. function stored in the USER-variable (R/W). This function
  4195. normally should use one of the loaders I/O-routines, which are
  4196. stored in the array R/WS. rwflag=0: read; rwflag<>0:write;
  4197.  
  4198.  
  4199.  
  4200.  
  4201.  
  4202. R/WS ( -- addr )
  4203.  
  4204. Vocabulary FORTH
  4205.  
  4206. Gives the address of an array, which holds the number and the
  4207. entry-addresses of the loaders I/O-functions to read/write a
  4208. block from/to the mass storage device. to the terminal. 'R/WS @
  4209. ' gives the number of the functions. 'R/WS 4+ @' is the address
  4210. of the first routine. The routines in this table may not be
  4211. executed from F68K because they need some interfacing provided
  4212. by R/W.
  4213.  
  4214.  
  4215.  
  4216.  
  4217.  
  4218. R> ( -- n )
  4219.  
  4220. Vocabulary FORTH
  4221.  
  4222. Pops a value from the returnstack onto the normal datastack.
  4223. This value should have been pushed onto the returnstack using
  4224. '>R', because addressconversion and -reconversion is done in a
  4225. '>R'-'R>' pair. See '>R'.
  4226.  
  4227.  
  4228.  
  4229.  
  4230.  
  4231. R@ ( -- n )
  4232.  
  4233. Vocabulary FORTH
  4234.  
  4235. Copies a value from the returnstack onto the normal datastack.
  4236. This value should have been pushed onto the returnstack using
  4237. '>R', because addressconversion and -reconversion is done in a
  4238. '>R'-'R@' pair. See '>R'.
  4239.  
  4240.  
  4241.  
  4242.  
  4243.  
  4244. READSYS ( addr count -- flag )
  4245.  
  4246. Vocabulary FORTH
  4247.  
  4248. Reads 'count' bytes to the buffer 'addr' in a systemdependent
  4249. manner. READSYS calls a routine supplied by the loader.
  4250.  
  4251.  
  4252.  
  4253.  
  4254.  
  4255. READSYSES ( -- addr )
  4256.  
  4257. Vocabulary FORTH
  4258.  
  4259. Gives the address of an array, which holds the number and the
  4260. entry-addresses of the loaders I/O-functions to read from a
  4261. file in a system dependent manner. 'READSYSES @' gives the
  4262. number of the functions. 'READSYSES 4+ @' is the address of the
  4263. first routine. The routines in this table may not be executed
  4264. from F68K because they need some interfacing provided by
  4265. READSYS.
  4266.  
  4267.  
  4268.  
  4269.  
  4270.  
  4271. RESTORE_STREAM ( -- )
  4272.  
  4273. Vocabulary FORTH
  4274.  
  4275. Restores the actual streamcontext from the returnstack. So it
  4276. can only be used in conjunction with SAVE_STREAM on one
  4277. executionlevel (because of the returnstackmanipulation).
  4278.  
  4279.  
  4280.  
  4281.  
  4282.  
  4283. ROWS ( -- addr )
  4284.  
  4285. Vocabulary FORTH
  4286.  
  4287. Variable which holds the number of available rows on the
  4288. current terminal.
  4289.  
  4290.  
  4291.  
  4292.  
  4293.  
  4294. RP! ( returnstackpointer -- )
  4295.  
  4296. Vocabulary FORTH
  4297.  
  4298. Set a new returnstack. Possibly can be used in conjunction with
  4299. RP@. Handle with care!
  4300.  
  4301.  
  4302.  
  4303.  
  4304.  
  4305. RP@ ( -- returnstackpointer )
  4306.  
  4307. Vocabulary FORTH
  4308.  
  4309. Gets the actual pointer to the bottom of the returnstack. Note
  4310. that 'R@' cannot be replaced by 'RP@ @' because
  4311. addressconversion is done within 'R@'. It can be replaced by
  4312. 'RP@ @ (ABSCODE)' doing the reconverion 'by hand'.
  4313.  
  4314.  
  4315.  
  4316.  
  4317.  
  4318. SAVE-SYSTEM ( -- )
  4319.  
  4320. Vocabulary FORTH
  4321.  
  4322. Uses the WRITESYS-function to create a new image of F68K, which
  4323. can be reloaded by the system-dependend loader.
  4324.  
  4325.  
  4326.  
  4327.  
  4328.  
  4329. SAVE_STREAM ( -- )
  4330.  
  4331. Vocabulary FORTH
  4332.  
  4333. Saves the actual streamcontext on the returnstack. This context
  4334. may be changes afterwards but has to be restored by
  4335. RESTORE_CONTEXT on the same executionlevel (because of the
  4336. returnstackmanipulation).
  4337.  
  4338.  
  4339.  
  4340.  
  4341.  
  4342. SAVEAREA ( addr count -- )
  4343.  
  4344. Vocabulary FORTH
  4345.  
  4346. Same as PUSH, but for an area of memory. count bytes from addr
  4347. will be saved on the returnstack and be restored with the next
  4348. 'EXIT' or ';' statement. It is used within 'EVALUATE' in order
  4349. to save the content of TIB.
  4350.  
  4351.  
  4352.  
  4353.  
  4354.  
  4355. SBLK ( -- addr )
  4356.  
  4357. Vocabulary BLOCKSTREAM
  4358.  
  4359. This is a USER-variable which contains the number of the
  4360. logical block actually loaded. Use SBLK instead of BLK when
  4361. working with blockstreams.
  4362.  
  4363.  
  4364.  
  4365.  
  4366.  
  4367. SPACE ( -- )
  4368.  
  4369. Vocabulary FORTH
  4370.  
  4371. Emits the constant BL =$20 to the terminal.
  4372.  
  4373. Example:
  4374. : space ( -- ) bl emit ;
  4375.  
  4376.  
  4377.  
  4378.  
  4379. SPACES ( n -- )
  4380.  
  4381. Vocabulary FORTH
  4382.  
  4383. Executes SPACE in a loop.
  4384.  
  4385.  
  4386.  
  4387.  
  4388.  
  4389. STREAM: ( -- ) \ STREAM: <name>
  4390.  
  4391. Vocabulary BLOCKSTREAM
  4392.  
  4393. Defining word for streamstructures. One example is USESTREAM
  4394. used by USE.
  4395.  
  4396. Example:
  4397. STREAM:XX
  4398. XX " TEST" ?BUSE
  4399.  
  4400.  
  4401.  
  4402.  
  4403. STREAMS ( -- )
  4404.  
  4405. Vocabulary FORTH
  4406.  
  4407. Invokes the blockstreamsystem. Now BLOCK, LOAD and BUFFER
  4408. access the logical blocks within the system. The variable
  4409. ROOTBLK is cleared and must to be changed!
  4410.  
  4411.  
  4412.  
  4413.  
  4414.  
  4415. TAB ( n -- )
  4416.  
  4417. Vocabulary FORTH
  4418.  
  4419. Moves the cursor to column n in the actual line. TAB uses OUT
  4420. to count the cursors position.
  4421.  
  4422.  
  4423.  
  4424.  
  4425.  
  4426. TOSS ( -- )
  4427.  
  4428. Vocabulary ONLY
  4429.  
  4430. 'TOSS' is a 'DROP' for the vocabulary-stack. It will often be
  4431. used in conjunction with 'ALSO', which increases the
  4432. vocabulary-stack.
  4433.  
  4434.  
  4435.  
  4436.  
  4437.  
  4438. UNLOOP ( -- )
  4439.  
  4440. Vocabulary FORTH
  4441.  
  4442. UNLOOP is used when it is necessary to EXIT a word from within
  4443. a DO-LOOP-structure.
  4444.  
  4445. Example:
  4446. ...
  4447.     DO ...
  4448.         IF unloop exit THEN ...
  4449.     LOOP ...
  4450.  
  4451.  
  4452.  
  4453.  
  4454. UNMOUNT ( -- )
  4455.  
  4456. Vocabulary FORTH
  4457.  
  4458. This will prepare a blockstream system to be copied to an other
  4459. device. From all physical blocknumbers contained in the system,
  4460. the number of the first physical block on the actual device
  4461. will be substracted. A later mount will reverse that procedure.
  4462. Always make sure that you are working with MOUNTed systems
  4463. only. Otherwise malfunction is guaranteed. It is not possible
  4464. to doubly UNMOUNT a system.
  4465.  
  4466.  
  4467.  
  4468.  
  4469.  
  4470. USE ( -- ) \ USE <name>
  4471.  
  4472. Vocabulary FORTH
  4473.  
  4474. This will open the blockstream with the name <name> for usage.
  4475. A STREAM: structure called USESTREAM will be filled with the
  4476. data of the selected stream. Notice that if a blockstream has
  4477. been created with MAKE, then USE must be supplied additionally.
  4478.  
  4479.  
  4480.  
  4481.  
  4482.  
  4483. USER ( -- ) \ USER <name>
  4484.  
  4485. Vocabulary FORTH
  4486.  
  4487. Creates a new USER-variable with the given name.
  4488.  
  4489.  
  4490.  
  4491.  
  4492.  
  4493. USESTREAM ( -- addr )
  4494.  
  4495. Vocabulary BLOCKSTREAM
  4496.  
  4497. This is a structure created with STREAM:. It is used by USE.
  4498.  
  4499.  
  4500.  
  4501.  
  4502.  
  4503. VALUE ( n -- ) \ <n> VALUE <name>
  4504.  
  4505. Vocabulary FORTH
  4506.  
  4507. Creates a VALUE-type. VALUEs can be read out using <name> and
  4508. be written using 'TO <name>'.
  4509.  
  4510. Example:
  4511. 27 VALUE X
  4512. X .         --> 27
  4513. 35 TO X
  4514. X .         --> 35
  4515.  
  4516.  
  4517.  
  4518.  
  4519. VER ( -- n )
  4520.  
  4521. Vocabulary FORTH
  4522.  
  4523. Gives the BCD representation of the date the kernel has been
  4524. created. E.g. if the kernel has been assembled on 6-12-91 the
  4525. following sequence will yield '19910612':
  4526.  
  4527. Example:
  4528. HEX VER .
  4529. \ This makes it possible to compare
  4530. \ different versions using
  4531. \ standard operators like < or >.
  4532.  
  4533.  
  4534.  
  4535.  
  4536. VIEW ( -- ) \ view <name>
  4537.  
  4538. Vocabulary FORTH
  4539.  
  4540. Looks for the source of the word with the given name. The
  4541. appropriate screen will be displaid.
  4542.  
  4543. Example:
  4544. view view
  4545.  
  4546.  
  4547.  
  4548.  
  4549. VOC' ( -- vocaddr ) \ voc' <vocname>
  4550.  
  4551. Vocabulary FORTH
  4552.  
  4553. Finds the address of the named vocabulary. This may be very
  4554. usefull together with searching word VOCSEARCH. The returned
  4555. address corresponds to those held in CURRENT or CONTEXT.
  4556.  
  4557. Example:
  4558. " DUP" voc' forth vocsearch
  4559.  
  4560.  
  4561.  
  4562.  
  4563. VOCABULARY ( -- ) \ VOCABULARY <name>
  4564.  
  4565. Vocabulary FORTH
  4566.  
  4567. Defines a new vocabulary with the given name. The vocabulary is
  4568. created only, it is not located within search order. The use of
  4569. vocabularies is highly recommended in order to keep the number
  4570. of words in the main vocabulary FORTH as small as possible.
  4571.  
  4572.  
  4573.  
  4574.  
  4575.  
  4576. VOCS ( -- )
  4577.  
  4578. Vocabulary FORTH
  4579.  
  4580. Prints a list of all vocabularies.
  4581.  
  4582.  
  4583.  
  4584.  
  4585.  
  4586. VOCSEARCH ( string vocaddr -- controlword cfa | string -1 )
  4587.  
  4588. Vocabulary FORTH
  4589.  
  4590. Searches for a word with the name given with the string in the
  4591. specified vocabulary. The address of the vocabulary comes from
  4592. CONTEXT, CURRENT or VOC'. VOCSEARCH is used by (FIND.
  4593.  
  4594. Example:
  4595. " DUP" voc' forth vocsearch
  4596.  
  4597.  
  4598.  
  4599.  
  4600. WRITESYS ( addr count -- flag )
  4601.  
  4602. Vocabulary FORTH
  4603.  
  4604. Writes 'count' bytes from the buffer 'addr' in a
  4605. systemdependent manner. WRITESYS calls a routine supplied by
  4606. the loader, which is stored in the USER-variable ^WRITESYS.
  4607.  
  4608.  
  4609.  
  4610.  
  4611.  
  4612. WRITESYSES ( -- addr )
  4613.  
  4614. Vocabulary FORTH
  4615.  
  4616. Gives the address of an array, which holds the number and the
  4617. entry-addresses of the loaders I/O-functions to write to a file
  4618. in a system dependent manner. 'WRITESYSES @' gives the number
  4619. of the functions. 'WRITESYSES CELL+ @' is the address of the
  4620. first routine. The routines in this table may not be executed
  4621. from F68K because they need some interfacing provided by
  4622. WRITESYS.
  4623.