home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume1 / cforth / part1 next >
Encoding:
Internet Message Format  |  1986-11-30  |  27.4 KB

  1. Date: Tue, 30 Apr 85 15:19:04 est
  2. From: mit-eddie!ihnp4!purdue!iuvax!apratt (Allan Pratt)
  3. Subject: FORTH INTERPRETER IN C (Part 1 of 3)
  4.  
  5. : Run this shell script with "sh" not "csh"
  6. PATH=:/bin:/usr/bin:/usr/ucb
  7. export PATH
  8. echo 'x - forth.doc'
  9. sed 's/^X//' <<'//go.sysin dd *' >forth.doc
  10. C-FORTH: a portable, C-coded figFORTH interpreter.
  11.  
  12. Written by Allan Pratt; completed April 1985.
  13.  
  14. This is a FORTH interpreter written entirely in portable C and FORTH. It
  15. requires nothing more than a decent C compiler to use.  It is not exactly
  16. fast or efficient, but it is a true FORTH interpreter.
  17.  
  18. The features include:
  19.  
  20. Bootstrapping threaded definitions from a near-FORTH dictionary file.
  21. Block file I/O.
  22. Execution tracing and single-stepping.
  23. Breakpoint detection, dumping the stack at the breakpoint.
  24. Saving and automatic restoration of the FORTH environment.
  25. Ability to convert the block file to a line-editor-compatible file, and back.
  26.  
  27. Included with the interpreter is a block file containing:
  28.  
  29. An UNTHREAD utility.
  30. A screen editor with key-binding and cursor-addressing.
  31.  
  32.  
  33. BRINGING UP THE INTERPRETER:
  34.  
  35. THIS FORTH MODEL REQUIRES "int"s TO BE TWICE THE SIZE OF "short"s,
  36. and "short"s to be 16 bits. I realize this is a barrier to portability,
  37. but you can change occurrances of "int" to "long" and "short" to "int" if
  38. "long"s are twice the size of "int"s.
  39.  
  40. Note also that model sizes greater than 32K (with 16-bit cells) are likely
  41. to fail because of the sign bit. This has not been adequately tested.
  42.  
  43. The first four sections of the file "common.h" contain implementation-dependent
  44. constants. These are TRACE, BREAKPOINT, several default file names, INITMEM,
  45. MAXMEM, and NSCR. As distributed, the FORTH system will work on most systems,
  46. but especially virtual-memory systems. If you do not have virtual memory, you
  47. will want to change MAXMEM -- see common.h for instructions.
  48.  
  49. Once you've configured common.h to your taste, compile the files with
  50.  
  51.     touch lex.yy.c
  52.     make all
  53.  
  54. Note that lex.yy.c is lex output from forth.lex, slightly modified (using
  55. sed). lex.yy.c is included in the distribution because not everybody has
  56. lex and sed. You touch lex.yy.c before make-ing so make doesn't try to remake
  57. it.
  58.  
  59. This make will create several files. Notable among them are "nf", the
  60. bootstrapper, "forth.core", the core-image output of nf, and "forth", the
  61. interpreter itself. Finally, there are two utility filters, b2l and l2b. These
  62. convert files from block format to line format and back (b2l --> block to
  63. line). A line-format file is one suitable for editing with vi or emacs: it
  64. consists of a header line for each screen, followed by 16 newline-separated
  65. lines of text for that screen, followed by the next screen. THERE MUST ALWAYS
  66. BE SIXTEEN LINES BETWEEN HEADERS in the line file, or l2b won't work properly.
  67.  
  68. You must use l2b to create the block file "forth.block" from "forth.line". Use:
  69.  
  70.     l2b < forth.line > forth.block
  71.  
  72. to do this.  If you don't have I/O redirection, I'm afraid you'll have to
  73. patch these programs (and lex.yy.c and nf.c, for that matter) to take 
  74. arguments or use default files.
  75.  
  76. Note that "forth.block" is the default block file used by FORTH. You can change
  77. this default in "common.h", and you can change it on the FORTH command line
  78. with -f.
  79.  
  80. Now that you have the interpreter ("forth"), the block file
  81. ("forth.block"), and the core file ("forth.core"), you are ready to
  82. roll. Invoke FORTH with the following line to the C-shell:
  83.  
  84.     stty -echo cbreak ; forth ; stty echo -cbreak
  85.  
  86. Some notes while running FORTH:
  87.  
  88. The backspace character is ^H, no matter what your terminal is set for. When
  89. you backspace, ASCII 8 gets sent to the screen, so the cursor should back up
  90. but not erase the letter you're backing up over. There is no kill character
  91. to wipe out an entire line. If you backspace beyond the beginning of the line,
  92. you will get a beep.
  93.  
  94. Don't use tabs; FORTH doesn't recognize them as whitespace.
  95.  
  96. Everything in the FORTH world is upper-case. Use caps-lock if you have one.
  97.  
  98. The VLIST command lists the FORTH vocabulary.
  99.  
  100. Some commands, like LIST and VLIST, use the FORTH word ?TERMINAL to see
  101. if the user wants to quit. Use your interrupt character (usually ^C) to
  102. stop these commands.  If you hit ^C twice before ?TERMINAL is checked,
  103. then you'll get an ABORT back to the FORTH top level. If the FORTH program
  104. is waiting for keyboard input, you'll have to hit ^C twice and then hit
  105. a normal key to see this effect. Your Quit character (often ^\) still works
  106. to get you back to your shell.
  107.  
  108. When you start FORTH up, it will tell you the number of blocks in the
  109. block file (either the default or the one you specified with -f). You can
  110. see a block with the LIST command: "3 LIST" will list block number 3. Block
  111. zero is special: because of a bug in the FORTH standard model, you can't
  112. see block zero until you've accessed many other blocks (where "many" is the
  113. number NSCR from "common.h").
  114.  
  115. In any case, you can load the UNTHREAD utility (see below) with "1 LOAD"
  116. (because it starts on block 1), and the editor with "10 LOAD".
  117.  
  118. XFORTH uses "setbuf(stdout,0)" in "forth.c" to force standard output to
  119. be unbuffered.  If this call doesn't work for you, just remove it, and
  120. standard output will be line buffered. If that is the case, change
  121. EXPECT (in "forth.dict"): replace the EMIT call with DROP. Then you can
  122. call forth directly, without the stty stuff. You use your own erase and kill
  123. characters, but the editor won't work.
  124.  
  125. SAVING THE FORTH ENVIRONMENT:
  126.  
  127. When you have been working in FORTH for a while, you will have developed
  128. words which you'd like to save, without having to reload them from the
  129. block file all the time. The word SAVE will save the current core image on
  130. a file, normally "forth.newcore", and exit. The -s flag changes the save
  131. file name.
  132.  
  133. When you start FORTH, the core file (either "forth.core" or the one specified
  134. with -c) is checked to see if it is a saved image or a bootstrapped image.
  135. If it's a saved image, execution begins from the spot it left off from.
  136. If it's bootstrapped (fresh out of nf), execution begins at COLD.
  137.  
  138. SUMMARY OF COMMAND-LINE OPTIONS:
  139.  
  140. -t[n]        trace; n is a digit from 0 to 9, default 0.
  141.  
  142.         Each time through the inner interpreter, a line will be printed
  143. out showing the current stack pointer, the top n stack elements
  144. (topmost at the left), the current interpretive pointer (ip), an indent
  145. to reflect the current nesting depth (actually the return-stack depth),
  146. and the name of the word about to be executed. N is the "trace depth";
  147. see DOTRACE below.
  148.  
  149. -d[n]        debug; n is a digit from 0 to 9, default 0.
  150.  
  151.     Like -t, -d prints out the trace line each time through the inner
  152. interpreter.  Unlike -t, it will then wait for input from the terminal. If
  153. you hit newline (Return, CR, etc.) it will proceed. If you type any key
  154. followed by newline, it will dump the current memory image to the dump file,
  155. usually "forth.dump", and then continue.
  156.  
  157. -n        no setbuf.
  158.     If -n is present, the setbuf(stdout,NULL) call which makes stdout
  159. unbuffered instead of line-buffered will not be executed. This is useful if
  160. you intend to do debugging with -t, -d, or the TRON command (see below).
  161.  
  162. -p xxxx        breakPoint.
  163.     Breakpoints are enabled, and one is set at address xxxx (in hex).
  164. Each time through the inner interpreter, the ip address is checked against
  165. this breakpoint address. If they match, "Breakpoint" is printed, along with
  166. the current stack pointer and the entire contents of the stack, with the
  167. topmost element at the left.
  168.  
  169. -c corename    set the core file name
  170.     The memory image will be read from this file instead of the default,
  171. which is usually "forth.core".
  172.  
  173. -b blockname    set the block file name
  174.     This file will be used as the block file for disk reads and writes,
  175. instead of the default block file, which is usually "forth.block".
  176.  
  177. -s savename    set the core-save file name
  178.     This file will be created or overwritten upon execution of the (SAVE)
  179. primitive (which is called by the SAVE command).  It will contain a core image
  180. (just like forth.core or the -c name) which reflects the current status at the
  181. time of the save. If this file is used as input (renamed to "forth.core" or
  182. used in -c later), the FORTH system will restart right where it left off.
  183. Note that -c and -s MAY use the same name.
  184.  
  185. DEPARTURES FROM THE figFORTH-79 STANDARD:
  186. ---------- ---- --- -------- -- --------
  187.  
  188. There are two features of the FORTH-79 standard which are unimplemented in
  189. this system: the <BUILDS ... DOES> construct and VOCABULARIES. Both of these
  190. are unimplemented simply because I couldn't understand the documentation
  191. sufficiently to implement them.  In any case, they do not affect the operation
  192. of FORTH, except inasmuch as the dictionary is simply a flat stack structure,
  193. and defining-words using DOES simply don't work.
  194.  
  195. EXTENSIONS FROM THE figFORTH-79 STANDARD:
  196. ---------- ---- --- -------- -- --------
  197.  
  198. I grew a FORTH implementation from the Z80 figFORTH standard, and found the
  199. following extensions to be vital to my sanity as a programmer and developer.
  200.  
  201. CASE c1 OF action1 ENDOF c2 OF action2 ENDOF default-action ENDCASE
  202.  
  203. This construct comes from Doctor Dobb's Journal, Number 59, September, 1984,
  204. in an article by Ray Duncan. 
  205.  
  206. I used to find that nesting IFs to emulate a CASE structure was the most
  207. difficult part of programming in FORTH, but now I don't have to mess with
  208. it any more.
  209.  
  210. \ (backslash)
  211.  
  212. This word begins a comment which extends to the end of the current line.
  213. This is only meaningful while loading, and causes an error if you are not
  214. loading.  It amounts to an open-paren where the end of the line is the closing
  215. paren. This, too, comes from Dr. Dobb's Journal, Number 59, in a different
  216. article, by Henry Laxen.
  217.  
  218. TRON, TROFF, DOTRACE
  219.  
  220. These provide tracing facilities for C-FORTH.  TRON takes one parameter, which
  221. is the number of stack elements to show. TROFF disables tracing. DOTRACE
  222. traces once, using the most recent depth value (from TRON or -tn on the command
  223. line). TRON will have no effect (but will still consume its argument) if
  224. the FORTH system was compiled without the TRACE flag set. DOTRACE, however,
  225. will still trace one line as advertised.
  226.  
  227. REFORTH
  228.  
  229. This word is useful when loading screens, to get the user's input. It
  230. reads one line from the terminal (with QUERY) and interprets it (with
  231. INTERPRET), then returns to the caller. This is used in the editor (see
  232. below) to read in the user's terminal type. This is yet another construct
  233. from Ray Duncan's article in Dr. Dobb's Journal, Number 59.
  234.  
  235. ALIAS        usage: ALIAS NEW OLD
  236.  
  237. This word is used to change the meaning of an existing word, after it
  238. has been used in defining other words.  Say you want to change EMIT so
  239. it forces a CR when the current column (user var OUT) equals the number
  240. of characters per line (constant C/L). The current definition of EMIT
  241. is:
  242.  
  243. : EMIT
  244.   (EMIT)
  245.   1 OUT !+
  246. ;
  247.  
  248. You could define a new word, NEWEMIT, as follows:
  249.  
  250. : NEWEMIT
  251.   OUT @ C/L = IF
  252.     CR
  253.   THEN
  254.   (EMIT)
  255.   1 OUT +!
  256. ;
  257.  
  258. and use ALIAS NEWEMIT EMIT to make all previous references to EMIT execute
  259. NEWEMIT instead. This is accomplished by making the definition of EMIT read:
  260.  
  261. : EMIT
  262.   NEWEMIT
  263. ;
  264.  
  265. (Note that my CR sets OUT to zero, so this really would work.)
  266.  
  267. NOTES ON THE BOOTSTRAP DICTIONARY:
  268. ----- -- --- --------- ----------
  269.  
  270. The contents of forth.dict describe the initial FORTH dictionary. There are
  271. several types of things in this file; they will be described by example.
  272.  
  273. PRIM (EMIT) 12        (primitive)
  274.  
  275. This declares a primitive called "(EMIT)", with an execute-code of 12. This
  276. execute-code is an index into the great switch statement in the inner
  277. interpreter, next(). In a real FORTH system, this would be an address where
  278. the actual code for the (EMIT) primitive resided.
  279.  
  280. To add primitives, you must do the following:
  281. 1. Add the primitive to forth.dict, using an unused execute-code.
  282.  
  283. 2. Come up with a name for that primitive which is a legal C identifier.
  284.    Convention for parenthesis, like (EMIT), is PEMIT. For brackets, BEMIT.
  285.    For slash (like "C/L") is CSLL, where SL stands for slash.
  286.  
  287. 3. Add the C identifier name to "forth.h", with the execute-code as its
  288.    value, like this:
  289.  
  290.     #define PEMIT 12
  291.  
  292. 4. In "prims.c", add the code for the primitive, as a function with
  293.    the same name as the #define above, except in lower case:
  294.  
  295.     pemit()
  296.     {
  297.         putchar(pop());
  298.     }
  299.  
  300. 5. In "forth.c", tack another case onto the switch statement in next():
  301.  
  302.             case PEMIT: pemit(); break;
  303.  
  304. 6. Recompile (preferably with make). You will need to recompile everything
  305.    but nf (which uses nf.c, lex.yy.c, and common.h, none of which you
  306.    changed). That is, you need to regenerate "forth" from forth.c, prims.c,
  307.    forth.h, and prims.h, and "forth.core" by throwing "forth.dict" at nf.
  308.  
  309. There is one special primitive: EXECUTE must be primitive number zero, since
  310. it violates structure and jumps into the middle of next(). It is handled as
  311. a special case in the code for NEXT, and it must be primitive number zero.
  312.  
  313. So much for primitives; there are other things in the forth.dict file:
  314.  
  315. CONST C/L 64    (constant)
  316.  
  317. Define constants with the word CONST followed by the name of the constant
  318. and its value.
  319.  
  320. USER OUT 36    (user variable)
  321.  
  322. Define user variables with the word USER followed by the name of the variable
  323. followed by the offset in the user-variable list of that variable.
  324.  
  325. The cold-start values for user variables are defined in common.h; they
  326. get copied into the initial forth.dict by nf, into the "cold-start defaults"
  327. area of memory.  They are copied from there into the first few user-variable
  328. locations by COLD.
  329.  
  330. VAR USE 0    (variable)
  331.  
  332. Define variables with the word VAR followed by the name of the variable
  333. followed by its initial value.
  334.  
  335. : EMIT        (colon-definition)
  336.  
  337. Begin colon-definitions with a colon (of course), followed by the name of
  338. the word.  Follow that with the words which make up the definition, ending
  339. with ; for normal words or ;* for immediate words.
  340.  
  341. There are two special colon-definitions: {NULL} and COLD. {NULL} is a special
  342. symbol which, when it is the name for a colon-definition, gets translated into
  343. a single null byte; the special name '\0'.  This is necessary since you
  344. can't type a null byte into a file, and C would mess up anyway, thinking
  345. the null was a terminator and not part of the string.  COLD is a special word
  346. in that it MUST BE DEFINED. The bootstrapper, nf, compiles the CFA of COLD
  347. into a special place in low memory, where the interpreter knows it can
  348. start executing threaded code.
  349.  
  350. LABEL 
  351.  
  352. Labels are used as the targets of branches. They are handled in much the
  353. same way as colon definitions and other words in the dictionary, in terms
  354. of forward referencing and so on. For this reason, LABELS MUST BE UNIQUE
  355. WORDS. You can't have a label which is the same as any other word in the
  356. dictionary, or you'll get a "word redefined" error (or worse!).
  357.  
  358. Since the "nf" preprocessor does not execute FORTH code, it does not
  359. have the higher-level FORTH constructs like begin .. until or
  360. do .. loop. These must be implemented by the user, using the primitives
  361. BRANCH (unconditional branch), 0BRANCH (branch on top-of-stack == 0),
  362. (DO) (start a DO construct), and (LOOP) and (+LOOP) (the primitives
  363. which end loop constructs).  Each of BRANCH, 0BRANCH, (LOOP), and (+LOOP)
  364. should be followed by one of two things: a signed offset, where a zero
  365. offset branches to the address of the BRANCH (etc.) instruction; or
  366. a label tag, which will be compiled as the appropriate offset from the
  367. current location.
  368.  
  369. A FORTH word with a loop might look like this:
  370.  
  371. : ONE-TO-TEN
  372.   10 0 DO
  373.     I .
  374.   LOOP
  375. ;
  376.  
  377. This would be entered into the "forth.dict" file as follows:
  378.  
  379. : ONE-TO-TEN
  380.   LIT 10 0 (DO)
  381. LABEL LOOP1
  382.     I .
  383.   (LOOP) LOOP1
  384. ;
  385.  
  386. Note the placement of the LABEL directive AFTER the (DO). Note also the use
  387. of LIT before 10, but not before 0. See below under LIT for more details.
  388.  
  389. The branches are used to implement IF ... ELSE ... ENDIF constructs, as
  390. well as conditional looping like BEGIN ... WHILE ... REPEAT and
  391. BEGIN ... UNTIL.  Ordinary programming practices are called for here,
  392. with such standbys as branching over the "TRUE" branch of the IF when
  393. the predicate is false, and branching over the "FALSE" part after the
  394. TRUE part has executed (if the predicate was true).  If you need more
  395. guidance, study forth.dict, or don't bother.
  396.  
  397. " (quotation mark)
  398.  
  399. The quotation mark begins and ends a "STRING LITERAL", which is compiled
  400. into the dictionary as a count byte followed by the bytes in the string,
  401. from left to right.  This is useful for the primitive (."), which expects
  402. a string of this form to follow it in the dictionary.  Within quotation
  403. marks, a backslash (\) will escape any character, including a quotation
  404. mark or another backslash, so:
  405.  
  406.     "He said, \"Backslash (\\) is best.\""
  407.         produces
  408.     [33] He said, "Backslash (\) is best."
  409.  
  410. where [33] is the length count.
  411.  
  412. Note that backslash escape conventions like \n, \t, etc. DO NOT WORK
  413. IN STRING LITERALS. This is a bug, not a feature.
  414.  
  415. 'x' (character literal surrounded by apostrophes)
  416.  
  417. Character-literal translation is done between single quotes, with the
  418. following effects:
  419.  
  420.     Text    produces
  421.     'A'       the value of the character A.
  422.     '\b'       system-dependent backspace character
  423.     '\f'                form-feed 
  424.     '\n'                newline
  425.     '\r'                carriage return
  426.     '\t'                tab
  427.     '\\'       the value of the character backslash
  428.     '''       the value of the character apostrophe.
  429.  
  430. These values are only meaningfully used after LIT commands; see below.
  431.  
  432. LIT
  433.  
  434. LIT must be used before all literal values in the dictionary, just as it
  435. is used (though the user doesn't see it) when words are defined. The
  436. forth.dict file, after all, represents a de-compiled FORTH memory image.
  437. It has all the BRANCHes and (LOOP)s showing, and it also has LITs showing.
  438.  
  439. In the above example for looping, LIT was used before 10, but not before
  440. 0. This is because "0" is defined a a CONSTant earlier in the forth.dict
  441. file.  To keep this straight, you should keep the following in mind:
  442. When you are in the middle of a definition, each word you type will have
  443. its CFA compiled into the dictionary.  If the word you type is not defined
  444. yet, nf looks at its "hint" about the string of characters: do they form a
  445. number, like a one and a zero form ten?  Do they form a hexadecimal number,
  446. like 0x10? Is it an octal literal, like 077? Is it a character literal, 
  447. like 'A'? If none of these is the case, then a zero is compiled as a place
  448. holder, and the word is considered a FORWARD REFERENCE to something yet to
  449. be defined. 
  450.  
  451. Yes, forward references are handled, and the distinction of
  452. defined words and labels is preserved: labels, instead of compiling their
  453. CFA into the dictionary, compile the offset of their CFA from the current
  454. dictionary pointer (minus one). If, at the end of the input file, there
  455. are still unresolved forward references, they will be listed. If the
  456. words containing the forward references are never executed, there will
  457. be no problem. If those words ARE executed, FORTH will bomb with a message
  458. like "Attempt to execute illegal primitive."
  459.  
  460. One snag is that you have to remember what numbers are defined as CONSTants,
  461. and what numbers aren't. If nf sees "LIT 1" it will compile the CFA of LIT,
  462. then the CFA of 1, because 1 has already been defined as a constant.
  463.  
  464. LIT must precede decimal, hex, octal, and character literals, but not 
  465. string literals.  If one of these literals is not preceded by LIT, a
  466. warning is issued, since this is unusual behavior. No warning is issued
  467. if LIT is succeeded by something other than a literal-class item, because
  468. that is not so unusual.
  469.  
  470.  
  471. INSTALLER'S GUIDE FOR THE SCREEN EDITOR:
  472. --------- - ----- --- --- ------ ------
  473.  
  474. This is an editor which I wrote on my Osborne 1, which has a memory-mapped
  475. display. I hacked out that part and hacked in the screen updating using .LINE,
  476. but at anything lower than 9600 BAUD I expect this to be intolerable.
  477.  
  478. When you get FORTH at your site, you will have to edit the line-file to
  479. include functions which clear the screen, locate the cursor, and enter and
  480. exit standout mode, named CLS, LOCATE, STANDOUT, and STANDEND, respectively.
  481. The trick for installing this is to put those functions in an unused screen
  482. (screens 8 and 9 are perfect for this), and place a CONSTANT in screen 10
  483. which is the name of the terminal (like "H19" or "ACT5") and has a value
  484. which is the number of the screen you put its definition in.  VT100 and
  485. ADM5 are included as models, in screens 6 and 7. ADM5 actually covers
  486. a broad range of terminals, from the old ADM3A to the TVI920C, though
  487. standout might not work the same any more. The two words STANDOUT and
  488. STANDEND can be null words, anyway.
  489.  
  490. USER'S GUIDE FOR THE EDITOR:
  491. ---- - ----- --- --- ------
  492.  
  493. This is a screen editor for FORTH screens. It will alter the file
  494. "forth.block" in the current directory, or whatever the installer set
  495. the default blockfile to be, or whatever you specify on the command
  496. line with the "-b file" switch.
  497.  
  498. You call a screen up with the EDIT command:
  499.  
  500.     3 EDIT
  501.  
  502. will begin editing screen 3.  The file starts with screen 0, but, due to
  503. a bug in figFORTH which I have carefully preserved (:-), you can't see
  504. screen 0 until you've edited several others -- as many as fit in memory,
  505. in fact. This number is 5 at the outset, but can be as low as 2 or as
  506. many as your installer's whim dictated. In any case, stick with screens
  507. numbered from 1 to the size of the block file as displayed when you
  508. started FORTH. 
  509.  
  510. When you start editing, the screen will clear, and the screen you asked
  511. for will appear. FORTH "screens" are, by convention and convenience,
  512. sixteen lines by sixty-four characters, for a total of 1K per screen.
  513. At the bottom of the screen being edited will be the word SCREEN and
  514. this screen's number.
  515.  
  516. The keys (as I've distributed the editor) match WordStar, to some extent.
  517. The cursor movement keys do, at any rate: ^E, ^D, ^X, ^S form a movement
  518. triangle at the left-hand side of the keyboard, moving one character or
  519. line at a time. The outer reaches of this triangle move even farther: 
  520. ^A and ^F move one word backward and forward, and ^R and ^C move one
  521. SCREEN backward and forward. If ^C is already your interrupt character,
  522. don't panic: use ESC-C (escape is a meta-prefix like in Emacs). If your
  523. network won't let you send ^S (like Sytek), ^H will do for backspace.
  524.  
  525. To see all the key bindings, use the FORTH command DESCRIBE-BINDINGS.
  526. To make a binding, do this:
  527.     1. Type "BIND-TO-KEY function <CR>"  where function is the name
  528.        of the command you want bound to a key, and <CR> means press
  529.        return/newline.
  530.     2. The computer will print "KEY: " at which time you should
  531.        strike the key you want to have that function bound to.
  532.        If you want something bound to ESC plus something, just press
  533.        escape followed by the key, exactly as you intend to use the
  534.        key in practice.
  535.  
  536. To see the binding for one key, use the command DESCRIBE-KEY. Again,
  537. you will be asked for the key you want described. Strike the key just
  538. as you normally do, with ESC before it if necessary.
  539.  
  540. The initial bindings are on screens 27 and 28 of the block file.
  541.  
  542. The editor is always in replace mode. That is, when you strike a key, it
  543. overwrites whatever was under the cursor.  There is no insert mode; I haven't
  544. gotten around to that.
  545.  
  546. As you go around changing things, you are only changing the image of the
  547. screen which FORTH keeps in memory; you are not changing the block file.
  548. You can mark the current screen for updating to the blockfile with ^U.
  549. This only marks the screen; it won't be written to the blockfile until
  550. the space is needed again, or you explicitly FLUSH the memory buffers.
  551. Use ESC-F (press escape, then press capital F) to mark the current screen
  552. for updating, and then FLUSH all marked screens (including this one, now)
  553. to the block file. Once you've done that, the change is permanent.
  554.  
  555. If you really mean to make a given change to a screen, mark it as updated
  556. (^U) right away. Countless hours have been wasted changing screens without
  557. marking them for writing, and then having that memory reused -- the changes
  558. are lost.
  559.  
  560. You can leave the editor with ESC-Q (for Quit).  Be sure to do an ESC-F
  561. before you do, if you want to save what you have. You can never be sure
  562. if your changes will get written out if you don't. (Yes, I know this
  563. is an oversimplification.)
  564.  
  565. You can leave FORTH by typing BYE.
  566.  
  567. XFINAL NOTES FROM THE AUTHOR:
  568. ----- ----- ---- --- ------
  569.  
  570. XFORTH runs slowly. If anybody can make this turkey fly (without, of course,
  571. rewriting it in assembly language), more power to you.  It was done as a
  572. Junior project at Indiana University, but in fact I learned more about
  573. project management and programmer/systems staff interaction than I did
  574. about implementing FORTH (which I had done previously in 8080 assembly
  575. code). In that sense it was profitable, and, since it works, I see no reason
  576. not to distribute it to the network. If you have comments of praise,
  577. I can be reached through the summer of 1985 at the address below;
  578. after that, I MAY be at iuvax!apratt.  Comments of another nature
  579. are not enthusiastically solicited, and I do NOT expect to upgrade this
  580. implementation AT ALL, EVER. Sorry, but there will be no "Version 2" for 
  581. this baby. If I have left crucial points out of this documentation,
  582. and my (hopefully-well-commented) code doesn't provide the answer,
  583. I will reply and possibly improve this documentation.  But for the
  584. most part, you're on your own.
  585.  
  586. As a parting shot, the inner interpreter's "switch" statement could
  587. be replaced by an array of functions, using the variable p as an
  588. index. I was not that ambitious, and I don't know if it would be faster
  589. than the table-lookup which my C compiler generates.
  590.  
  591.                     -- Allan Pratt
  592.                     APRATT.PA@XEROX.ARPA
  593.  
  594. QUICK SUMMARY OF FILES (THERE IS A MESS OF THEM!)
  595.  
  596. Makefile    supposed to bring them all together
  597. b2l.c and b2l    filter to convert block-files into line-files for editing
  598. l2b.c and l2b    filter to convert line-files into block-files for FORTH
  599.  
  600. common.h    This is a header file with configuration and common information
  601.         used by all C source files except lex.yy.c
  602.  
  603. forth.h        Header file with primitive numbers in it, among other things
  604. forth.c        source code for the guts/support functions for the interpreter
  605. prims.h        Header file with macro definitions for primitives
  606. prims.c        source code for primitives too complex for macros
  607.  
  608.         The above four files, plus common.h, contribute to the
  609.         executable "forth"
  610.  
  611. nf.c        source for the bootstrapper, which interprets the dictionary
  612.         and generates an initial memory image for FORTH
  613.  
  614. forth.lex    lex input for lexical analyzer used by nf.c
  615. forth.lex.h    header file used by lex.yy.c and nf.c
  616. lex.yy.c    lex output, modified (look at the Makefile)
  617.  
  618.         The above four files, plus common.h, contribute to the
  619.         executable "nf", the preprocessor.
  620.  
  621. forth.block    This is the (default) block-file used by FORTH for its
  622.         editing- and load-screens
  623.  
  624. forth.line    This file usually resembles forth.block, but is in a
  625.         format suitable for editing with emacs or vi: a header
  626.         line, followed by sixteen lines of trailing-blank-
  627.         truncated, newline-terminated text for each screen.
  628.  
  629.         If one of forth.line and forth.block is out of date with
  630.         respect to the other, you can bring it back up to date
  631.         with b2l or l2b, above.
  632.  
  633. forth.dict    This is a human-readable, pseudo-FORTH dictionary which
  634.         nf uses to generate the initial environment. It contains
  635.         forward references and no higher structures like DO..LOOP
  636.  
  637. forth.core    This is one output of nf: it contains the core image for
  638.         the FORTH environment, as dictated by common.h and forth.dict
  639.  
  640. forth.newcore    This is the file for holding core images saved with the (SAVE)
  641.         primitive. If FORTH is started with "-c forth.newcore", the
  642.         image is restarted right where it left off.
  643.  
  644. forth.map    This is another output of nf: it contains a human-readable
  645.         dump of the forth environment which nf generated. This can
  646.         be compared with the post-mortem dump which FORTH generates
  647.         in forth.dump in certain cases.
  648.  
  649. //go.sysin dd *
  650.