\ The Rest is Silence 04Apr84map************************************************************* ************************************************************* *** *** *** Please direct all questions, comments, and *** *** miscellaneous personal abuse to: *** *** *** *** Henry Laxen or Michael Perry *** *** 1259 Cornell Avenue 1125 Bancroft Way *** *** Berkeley, California Berkeley, California *** *** 94706 94702 *** *** *** ************************************************************* ************************************************************* \ Load Screen to Bring up Standard System 24Aug86nhm 2 LOAD ( Utilities ) 9 LOAD ( STRINGS ) 12 LOAD ( EDITING ) 28 LOAD ( DUMPING ) 31 LOAD ( SEEING ) 43 LOAD ( SHOWING ) 49 LOAD ( BUGGING ) CR .( Standard System Loaded ) \ Basic Utilities Load Screen 07Feb86nhmONLY FORTH ALSO DEFINITIONS : U<= (S u1 u2 -- f ) U> NOT ; : U>= (S u1 u2 -- f ) U< NOT ; : <= (S n1 n2 -- f ) > NOT ; : >= (S n1 n2 -- f ) < NOT ; : 0>= (S n1 n2 -- f ) 0< NOT ; : 0<= (S n1 n2 -- f ) 0> NOT ; VOCABULARY HIDDEN 1 6 +THRU \ Output Formatting 16Feb89nhmVARIABLE LMARGIN 0 LMARGIN ! VARIABLE RMARGIN 70 RMARGIN ! : ?LINE (S n -- ) #OUT @ + RMARGIN @ > IF CR LMARGIN @ SPACES THEN ; : ?CR (S -- ) 0 ?LINE ; : ?NEW #OUT @ LMARGIN @ > IF CR THEN ; \ Managing Source Screens 15Feb89cam: .SCR ." Scr # " SCR ? 8 SPACES FILE? ; : LINE (S scr l# -- adr len) C/L * SWAP BLOCK + C/L -TRAILING ; : LIST (S n) 1 ?ENOUGH CR DUP SCR ! .SCR L/SCR 0 DO CR I 3 .R SPACE DUP I LINE >TYPE KEY? ?LEAVE LOOP DROP CR ; : TRIAD (S n) 12 EMIT ( form feed ) 3 / 3 * 3 BOUNDS DO I LIST LOOP ; : .LINE0 (S n) DUP 3 MOD 0= IF CR THEN CR DUP 3 .R SPACE 0 LINE >TYPE ; : INDEX (S n1 n2) 2 ?ENOUGH 1+ SWAP DO I .LINE0 LOOP CR ; \ Display the WORDS in the Context Vocabulary 30Nov84nhm: LARGEST (S addr n -- addr' val ) OVER 0 SWAP ROT 0 DO 2DUP @ U< IF -ROT 2DROP DUP @ OVER THEN 2+ LOOP DROP ; : WORDS (S -- ) CR LMARGIN @ SPACES CONTEXT @ HERE #THREADS 2* CMOVE BEGIN HERE #THREADS LARGEST DUP WHILE DUP L>NAME DUP C@ 31 AND ?LINE .NAME SPACE SPACE @ SWAP ! KEY? IF EXIT THEN REPEAT 2DROP ; ROOT DEFINITIONS : WORDS WORDS ; FORTH DEFINITIONS \ Iterated Interpretation 18Feb86nhmVARIABLE #TIMES ( # times already performed ) 1 #TIMES ! : TIMES (S n -- ) 1 #TIMES +! #TIMES @ < IF 1 #TIMES ! ELSE >IN OFF THEN ; : MANY (S -- ) KEY? NOT IF >IN OFF THEN ; \ : WHEN (S f -- ) \ PAUSE NOT IF R> 4 - >R THEN ; : :: (S -- ) HERE >R [ ' : @ ] LITERAL , !CSP ] R@ EXECUTE R> DP ! ; \ Managing Source Screens 20Mar87nhm2VARIABLE VPTR DOS 1 FCB1 VPTR 2! : L [ DOS ] SCR @ FILE @ VPTR 2@ FILE ! LIST FILE ! SCR ! ; : N 1 VPTR 2+ +! DISK-ERROR OFF L ; : P -1 VPTR 2+ +! DISK-ERROR OFF L ; : ESTABLISH (S n -- ) FILE @ SWAP 1 BUFFER# 2! ; : (COPY) ( from to -- ) OFFSET @ + SWAP IN-BLOCK DROP ESTABLISH UPDATE ; : COPY FLUSH (COPY) FLUSH ; : @VIEW (S code-field -- scr file# ) >VIEW @ DUP 4095 AND DUP 0= ABORT" entered at terminal." SWAP 4096 / 15 AND ; : (VIEW) (S cfa -- ) [ DOS ] @VIEW ?DUP IF 2* VIEW-FILES + @ ." is in " >BODY ELSE ." may be in current file: " FILE @ THEN 2DUP .FILE ." screen " . DUP (OPEN-FILE) VPTR 2! ; : VIEW ' (VIEW) L ; \ Disk copy utility 08APR83HHLVARIABLE HOPPED ( # screens copy is offset ) VARIABLE U/D DEFER CONVEY-COPY ' (COPY) IS CONVEY-COPY : HOP ( n -- ) ( specifies n screens to skip ) HOPPED ! ; : .TO ( #1 #2 -- #1 #2 ) CR OVER . ." to " DUP . ; : (CONVEY) (S blk n -- blk+-n ) 0 ?DO KEY? ?LEAVE DUP DUP HOPPED @ + .TO CONVEY-COPY U/D @ + LOOP FLUSH ; : CONVEY (S first last -- ) FLUSH HOPPED @ 0< IF 1+ OVER - 1 ELSE DUP 1+ ROT - -1 THEN U/D ! #BUFFERS /MOD >R (CONVEY) R> 0 ?DO #BUFFERS (CONVEY) LOOP DROP ; : TO ( #1st-source #last-source -- #1st-source #last-source ) ( #1st-dest must follow TO ) SWAP BL WORD NUMBER DROP OVER - HOP SWAP ; \ String Functions Load Screen 07Feb84map 1 2 +THRU CR .( Strings Loaded ) \S The String manipulation primitives include string comparison andsearching. The string search implemented is used in the editor to find the desired string. The only unusual thing about it is the presence of a variable called CAPS, which determines whether or not to ignore the case of the subject and pattern strings. If case is ignored then A-Z = a-z. The default is ignore case. \ String Functions SEARCH 10Mar84mapVARIABLE FOUND : SCAN-1ST (S a n c -- a n ) CAPS @ IF DROP ELSE SCAN THEN ; : SEARCH ( sadr slen badr blen -- n f ) FOUND OFF SWAP >R 2DUP U<= IF OVER - 1+ 2 PICK C@ R@ -ROT >R BEGIN R@ SCAN-1ST DUP IF >R 3DUP SWAP COMPARE 0= IF FOUND ON R> DROP 0 >R THEN R> THEN DUP WHILE 1 /STRING REPEAT R> 2DROP -ROT THEN 2DROP R> - FOUND @ ; \ String operators 04Apr84map: DELETE (S buffer size count -- ) OVER MIN >R R@ - ( left over ) DUP 0> IF 2DUP SWAP DUP R@ + -ROT SWAP CMOVE THEN + R> BLANK ; : INSERT (S string length buffer size -- ) ROT OVER MIN >R R@ - ( left over ) OVER DUP R@ + ROT CMOVE> R> CMOVE ; : REPLACE (S string length buffer size -- ) ROT MIN CMOVE ; \ Load Screen for shadows 24Aug86nhm 1 2 +THRU ' (DEL-IN) IS BS-IN CR .( Shadow Loaded ) ONLY FORTH ALSO DEFINITIONS \ Shadow Screen Support 19Mar87nhmVOCABULARY SHADOW ALSO SHADOW DEFINITIONS : DISPLACEMENT (S fcb -- disp) [ DOS ] MAXREC# @ 1+ 0 [ 8 2* ] LITERAL UM/MOD NIP ; : (>SHADOW) (S scr# fcb -- scr#' ) DISPLACEMENT 2DUP < IF + ELSE - THEN ; : >SHADOW (S scr# -- scr#' ) FILE @ (>SHADOW) ; : >IN-SHADOW (S scr# -- scr#' ) IN-FILE @ (>SHADOW) ; ONLY FORTH ALSO DEFINITIONS : T (S -- ) VPTR 2@ [ SHADOW ] (>SHADOW) VPTR 2+ ! L ; \ Shadow Screen Support 24Aug86nhm ONLY FORTH ALSO SHADOW ALSO DEFINITIONS : COPY (S from to -- ) FLUSH 2DUP (COPY) >SHADOW SWAP >IN-SHADOW SWAP (COPY) FLUSH ; : CONVEY (S first last -- ) 2DUP CONVEY >IN-SHADOW SWAP >IN-SHADOW SWAP 0 >SHADOW 0 >IN-SHADOW - HOPPED +! CONVEY ; \ Load Screen for Dumping Utility 07Feb86nhm 1 2 +THRU CR .( Dumping Utility Loaded ) \S The dump utility gives you a formatted hex dump with the ascii text corresponding to the bytes on the right hand side of the screen. DUMP uses the default Forth segment, LDUMP takes the segment as an argument. \ General Dump Utility 07Feb86nhm : .2 (S n -- ) 0 <# # # #> TYPE SPACE ; : EMIT. (S char -- ) 127 AND DUP BL 126 BETWEEN NOT IF DROP ASCII . THEN EMIT ; : ?.N (S n1 n2 -- n1 ) 2DUP = IF ." \/" DROP ELSE 2 .R THEN SPACE ; : ?.A (S n1 n2 -- n1 ) 2DUP = IF ." V" DROP ELSE 1 .R THEN ; : .HEAD (S addr len -- addr' len' ) SWAP DUP -16 AND SWAP 15 AND CR 6 SPACES 8 0 DO I ?.N LOOP SPACE 16 8 DO I ?.N LOOP SPACE 16 0 DO I ?.A LOOP ROT + ; \ General Dump Utility 11Feb86nhm VARIABLE LDUMP-SEG : D.2 (S addr len -- ) BOUNDS ?DO LDUMP-SEG @ I C@L .2 LOOP ; : DLN (S addr --- ) CR DUP 4 U.R 2 SPACES 8 2DUP D.2 SPACE OVER + 8 D.2 SPACE 16 BOUNDS ?DO LDUMP-SEG @ I C@L EMIT. LOOP ; : LDUMP (S seg addr len -- ) ROT LDUMP-SEG ! BASE @ -ROT HEX .HEAD BOUNDS DO I DLN KEY? ?LEAVE 16 +LOOP BASE ! ; : DUMP (S addr len -- ) FORTH-SEG -ROT LDUMP ; \ Load Screen for Decompiler 07Feb84map 1 11 +THRU CR .( Decompiler Loaded ) \S A Forth decompiler is a utility program that translates executable forth code back into source code. Normally this is impossible, since traditional compilers produce more object code than source, but in Forth it is quite easy. The decompileris almost one to one, failing only to correctly decompile the various Forth control stuctures and special compiling words. It was written with modifiability in mind, so if you add your own special compiling words, it will be easy to change the decompiler to include them. This code is highly implementation dependant, and will NOT work on other Forth system. To invoke the decompiler, use the word SEE where is the name of a Forth word. \ Inline CASE statement using { and } 27Sep85nhm\ Note: subscripts start with 0 : C-ABORT CR ." Argument out of range -- tried " . ABORT ; CODE (CASE) (S arg# --) BX POP BX INC BX SHL IP BX ADD BX IP CMP U< IF BX 0 [IP] CMP U> IF 0 [IP] IP MOV 0 [BX] W MOV 0 [W] JMP THEN THEN IP BX SUB BX SAR BX DEC BX PUSH ' C-ABORT # W MOV 0 [W] JMP END-CODE : { COMPILE (CASE) ?>MARK LIT? OFF ; IMMEDIATE : } ?>RESOLVE LIT? @ ABORT" Literals in {} must be defined as constants" ; IMMEDIATE \ ASSOCIATIVE: Table Lookup Def. Word 01MAR82HHL : ASSOCIATIVE: CONSTANT DOES> (S N -- INDEX ) DUP @ ( N PFA CNT ) -ROT DUP @ 0 ( CNT N PFA CNT 0 ) DO 2+ 2DUP @ = ( CNT N PFA' BOOL ) IF 2DROP DROP I 0 0 LEAVE THEN ( CLEAR STACK AND RETURN INDEX THAT MATCHED ) LOOP 2DROP ; \ Decompile each type of word 07Feb86nhmDEFER (SEE) HIDDEN DEFINITIONS : .WORD (S IP -- IP' ) DUP @ >NAME .NAME 2+ ; : .INLINE (S IP -- IP' ) .WORD DUP @ . 2+ ; : .BRANCH (S IP -- IP' ) .WORD DUP @ OVER - . 2+ ; : .QUOTE (S IP -- IP' ) .WORD .WORD ; : .STRING (S IP -- IP' ) .WORD COUNT 2DUP TYPE SPACE + ; \ Decompile each type of word 28Feb84map: .(;CODE) (S IP -- IP' ) .WORD DOES? IF ." DOES> " ELSE DROP FALSE THEN ; : .UNNEST (S IP -- IP' ) ." ; " DROP 0 ; : .FINISH (S IP -- IP' ) .WORD DROP 0 ; \ Classify each word in a definition 23JUN83HHL14 ASSOCIATIVE: EXECUTION-CLASS ( 0 ) ' (LIT) , ( 1 ) ' ?BRANCH , ( 2 ) ' BRANCH , ( 3 ) ' (LOOP) , ( 4 ) ' (+LOOP) , ( 5 ) ' (DO) , ( 6 ) ' COMPILE , ( 7 ) ' (.") , ( 8 ) ' (ABORT") , ( 9 ) ' (;CODE) , ( 10 ) ' UNNEST , ( 11 ) ' (") , ( 12 ) ' (?DO) , ( 13 ) ' (;USES) , \ Classify each word in a definition 25Sep85nhm: .EXECUTION-CLASS { ( 0 ) .INLINE ( 1 ) .BRANCH ( 2 ) .BRANCH ( 3 ) .BRANCH ( 4 ) .BRANCH ( 6 ) .BRANCH ( 6 ) .QUOTE ( 7 ) .STRING ( 8 ) .STRING ( 9 ) .(;CODE) ( 10 ) .UNNEST ( 11 ) .STRING ( 12 ) .BRANCH ( 13 ) .FINISH ( 14 ) .WORD } ; \ Decompile a : definition 15Mar83map: .PFA (S CFA -- ) >BODY BEGIN ?CR DUP @ EXECUTION-CLASS .EXECUTION-CLASS DUP 0= KEY? OR UNTIL DROP ; : .IMMEDIATE (S CFA -- ) >NAME C@ 64 AND IF ." IMMEDIATE" THEN ; \ Display category of word 01Apr87nhm: .CONSTANT (S CFA -- ) DUP >BODY ? ." CONSTANT " >NAME .NAME ; : .VARIABLE (S CFA -- ) DUP >BODY U. ." VARIABLE " DUP >NAME .NAME ." Value = " >BODY ? ; : .: (S CFA -- ) ." : " DUP >NAME .NAME 2 SPACES .PFA ; : .DOES> (S CFA -- ) ." DOES> " BODY> .PFA ; : .USER-VARIABLE (S CFA -- ) DUP >BODY ? ." USER VARIABLE " DUP >NAME .NAME ." Value = " >IS ? ; \ Display category of word 13May86nhm: .DEFER (S CFA -- ) ." DEFERRED " DUP >NAME .NAME ." IS " >IS @ (SEE) ; : .OTHER (S CFA -- ) DUP >NAME .NAME DUP @ OVER >BODY = ( cfa points to the pfa in code words ) IF DROP ." is Code" EXIT THEN DUP @ DOES? IF .DOES> DROP EXIT THEN 2DROP ." uses Code" ; \ Classify a word based on its CFA 13May86nhm5 ASSOCIATIVE: DEFINITION-CLASS ( 0 ) ' QUIT @ , ( 1 ) ' 0 @ , ( 2 ) ' SCR @ , ( 3 ) ' BASE @ , ( 4 ) ' KEY @ , : .DEFINITION-CLASS { ( 0 ) .: ( 1 ) .CONSTANT ( 2 ) .VARIABLE ( 3 ) .USER-VARIABLE ( 4 ) .DEFER ( 5 ) .OTHER } ; \ Top level of the Decompiler SEE 29Sep83map: ((SEE)) (S Cfa -- ) CR DUP DUP @ DEFINITION-CLASS .DEFINITION-CLASS .IMMEDIATE ; ' ((SEE)) IS (SEE) FORTH DEFINITIONS : SEE (S -- ) ' (SEE) ; \ Load Screen for PRINT Utility 23Feb84mapONLY FORTH ALSO DEFINITIONS 1 5 +THRU CR .( Print Utility Loaded ) ONLY FORTH ALSO DEFINITIONS \S The Print Utility allows you to print a range of screens on your printer. If your printer allows it, you can print 6 screens per page. The top level word is SHOW which takes a starting and ending screen number and prints all the non blank screens within the range. SHOW in the EDITOR prints the screens and their shadows. The print utility is initialized by INIT-PR, which defaults to NOOP. If you have an EPSON MX-80 set INIT-PR to EPSON. If your printer cannot print 132 columns per line, then you should use TRIAD instead. \ Variables and Setup 06Jun85nhm: EPSON (S -- ) CONTROL O EMIT ( EPSON Condensed ) ; : CENTRONICS (S -- ) 27 EMIT 20 EMIT ( Condensed ) ; DEFER INIT-PR ' NOOP IS INIT-PR DEFER FOOTING 66 CONSTANT L/PAGE 0 CONSTANT LOGO VARIABLE #PAGE : PAGE (S -- ) DOES> PERFORM 1 #PAGE +! #LINE OFF #OUT OFF ; PAGE : FORM-FEED (S -- ) CONTROL M EMIT CONTROL L EMIT ; : (PAGE) (S -- ) L/PAGE #LINE @ OVER MIN ?DO CR LOOP ; ' (PAGE) IS PAGE : (SEMIT) (S c -- ) PRINTING @ IF (PRINT) ELSE (CONSOLE) THEN ; HIDDEN DEFINITIONS CREATE SCR#S 14 ALLOT ( enough room for 6 Screens ) \ Print 2 screens across on a page 10Apr84map: TEXT? (S Scr# -- f ) BLOCK DUP C@ BL ASCII ~ BETWEEN ( printable ) IF B/BUF -TRAILING NIP 0<> ( and not empty ) ELSE FALSE THEN ; : PR (S scr -- ) DUP CAPACITY >= IF DROP LOGO THEN 1 SCR#S +! SCR#S DUP @ 2* + ! ; : 2PR (S Scr1# Scr2# line# -- ) CR DUP 2 .R SPACE C/L * >R PAD 129 BLANK SWAP BLOCK R@ + PAD C/L CMOVE BLOCK R> + PAD C/L + 1+ C/L CMOVE PAD 129 -TRAILING TYPE ; : 2SCR (S Scr1 Scr2 --- ) CR CR 4 SPACES OVER 4 .R 61 SPACES DUP 4 .R 16 0 DO 2DUP I 2PR LOOP 2DROP ; \ Prints 6 screen on a page 19Mar87nhm: P-HEADING (S -- ) CR CR 5 SPACES ." Page# " #PAGE ? 8 SPACES FILE? CR ; : P-FOOTING (S -- ) CR CR 58 SPACES ." Forth 83 Model" PAGE ; ' P-FOOTING IS FOOTING VARIABLE SAVE-EMIT ' (EMIT) IS SAVE-EMIT : PR-START (S -- ) PRINTING ON #LINE OFF ['] EMIT >IS SAVE-EMIT @! ['] (SEMIT) IS EMIT SCR#S OFF 1 #PAGE ! INIT-PR ; : PR-STOP (S -- ) SAVE-EMIT @ IS EMIT PRINTING OFF ; \ Prints 6 screen on a page 22Sep85nhm : PR-PAGE (S -- ) P-HEADING SCR#S OFF SCR#S 2+ 3 0 DO DUP @ OVER 6 + @ 2SCR 2+ LOOP DROP FOOTING ; : PR-S-PAGE (S -- ) P-HEADING SCR#S OFF SCR#S 2+ 3 0 DO DUP @ OVER 2+ @ 2SCR 4 + LOOP DROP FOOTING ; : PR-FLUSH (S -- f ) SCR#S @ DUP ( Any screens left over? ) IF BEGIN SCR#S @ 5 < WHILE 0 PR REPEAT LOGO PR THEN 0<> ; \ Print Page with Shadows 03Apr84mapFORTH DEFINITIONS : SHOW (S first last -- ) [ HIDDEN ] PR-START 1+ SWAP ?DO I TEXT? IF I PR THEN SCR#S @ 6 = IF PR-PAGE THEN LOOP PR-FLUSH IF PR-PAGE THEN PR-STOP ; SHADOW DEFINITIONS : SHOW (S first last -- ) [ HIDDEN ALSO ] PR-START 1+ SWAP ?DO I TEXT? IF I PR I [ SHADOW ] >SHADOW PR THEN SCR#S @ 6 = IF PR-S-PAGE THEN LOOP PR-FLUSH IF PR-S-PAGE THEN PR-STOP ; ONLY FORTH ALSO DEFINITIONS : LISTING (S -- ) 0 CAPACITY 2/ 1- [ SHADOW ] SHOW ; \ Load Screen for Debugger Utility 07Feb84mapONLY FORTH ALSO DEFINITIONS 1 2 +THRU CR .( Debugger Hi Level Loaded ) ONLY FORTH ALSO DEFINITIONS \S The debugger is designed to let the user single step the execution of a high level definition. To invoke the debugger, type DEBUG XXX where XXX is the name of the word you wish to trace. When XXX executes, you will get a single step trace showing you the word within XXX that is about to execute, and the contents of the parameter stack. If you wish to poke around, type F and you can interpret Forth commands until you type RESUME, and execution of XXX will continue where it left off. This debugger works by patching the NEXT routine, so it is highly machine and implementation dependent. The same idea should work however on any Forth system with a centralized NEXT routine. \ Print a High Level Trace 30Nov84nhmBUG ALSO DEFINITIONS : L.ID (S nfa len -- ) SWAP DUP .NAME DUP NAME> 1- - + SPACES ; VARIABLE SLOW VARIABLE RES : (DEBUG) (S low-adr hi-adr -- ) 1 CNT ! IP> ! R .S R> CR @ >NAME 10 L.ID SLOW @ NOT KEY? OR IF SLOW OFF RES OFF ." --> " KEY UPC ASCII C OVER = IF SLOW @ NOT SLOW ! THEN ASCII F OVER = IF DROP BEGIN QUERY RUN RES @ UNTIL THEN ASCII Q OVER = ABORT" Unbug" DROP THEN PNEXT ; ' TRACE 'DEBUG ! FORTH DEFINITIONS : DEBUG (S -- ) ' 2- DUP [ BUG ] 'UNNEST (DEBUG) ; : RESUME (S -- ) [ BUG ] RES ON 0 PNEXT ; ONLY FORTH ALSO DEFINITIONS \ The Rest is Silence 04Apr84mapDon't be fooled by the screen on the left. There is more to come. This is the LOGO screen which will be printed in your listings as the very last screen, if space permits. ( Load Screen to Bring up Standard System 03Apr84map) STRINGS Character manipulation and case conversions EDITING The Starting Forth Editor, adapted to split screen DUMPING Formatted Hex dump of memory SEEING A decompiler utility SHOWING A print utility for screens with/without shadows BUGGING The High Level Trace Utility These are the machine independant utilities that are loaded when you want to bring up a standard system. There are no machine dependancies in this file. Even the decompiler is written in a machine independant manner. You may need to add some code to the CPUxx.4TH file to make this possible. \ Basic Utilities Load Screen 07Feb86nhm U<= Unsigned less than or equal. U>= Unsigned greater than or equal. <= Less than or equal. >= Greater than or equal. 0<= Less than or equal to zero. 0>= Greater than or equal to zero. HIDDEN is a vocabulary for internal routines to avoid cluttering up FORTH with all manner of junk. Used by the decompiler and print utilities. \ Output Formatting 03Apr84mapLMARGIN is the column number of the left margin. RMARGIN is the column number of the right margin. ?LINE Move to left margin on next line if we will be past the right margin after printing n characters. ?CR Move to left margin on next line if we are past the right margin. These words are useful for a variety of output formatting needs. Only WORDS uses the margins currently. See chapter 12 of Starting Forth for more ideas. \ LIST INDEX 07Feb86nhm.SCR (S -- ) Print current screen number and file name. LIST (S n -- ) List the specified screen as 16 lines with 64 characters each. Pressing a key aborts the listing. LIST also makes the specified screen the current screen. TRIAD (S n -- ) Lists three screens per page. For 80 column printers. .LINE0 (S n -- ) print line 0 of block n. INDEX (S n1 n2 -- ) Lists the first line of every screen, from n1 through n2. This is very useful for getting a quick idea of what is in a file if you use the first line of every screen as a global screen comment. \ Display the WORDS in the Context Vocabulary 03Apr84mapLARGEST (S addr n -- addr' val ) Given a address and a number of words to examine, return the address and the value of the largest entry in the array. WORDS (S -- ) List the words in the context vocabulary. This can be interrupted any time by pressing any key. Add WORDS to ROOT. \ Iterated Interpretation 03Apr84map#TIMES A variable that keeps track of how many times. TIMES ( n -- ) Re-execute the input stream a specified number of times. MANY (S -- ) Re-execute the input stream until the user presses a key. \ WHEN (S f -- ) \ Re-execute the previous word until it returns true. \ NOTE: WHEN is slightly magic. \ Usage: : TEST READY WHEN BEEP ; \ Where READY returns a flag. :: compile and execute nameless FORTH code, then forget it. \ Managing Source Screens 19Mar87nhmL List the current screen. N Make the Next screen the current one, and list it. P Make the Previous screen the current one, and list it. ESTABLISH Sets the block number of the most recently referenced block. (COPY) The primitive that copies one screen to another. COPY Copies and screen and flushes it to disk. @VIEW pick up the given view-field and partition it into screen number and file number. File number indexes VIEW-FILES.VIEW will display the name of the file and number of the screen containing the source code for . The file will be opened if possible and the screen listed. \ Disk copy utility 23MAY83HHLHOPPED The number of screens to skip when copying U/D the direction of the copy, to prevent overlap. CONVEY-COPY deferred so that it can be used in different contextHOP Specifies the number of screens to hop over. .TO Prints a message to keep the user happy. (CONVEY) (S blk n -- blk+-n ) Moves a set of screens in the direction of the copy. CONVEY (S first last -- ) Moves a set of screens by first determining the direction to prevent overlap, and then moving them as a set whose size is determined by the number of available buffers. TO ( #1st-source #last-source -- #1st-source #last-source ) You can use TO instead of HOP if you know the destination screen number instead of the number of screens to skip. \ String Functions Case Conversions 10Mar84mapFOUND A local variable to make life easier. SCAN-1ST SCAN for first character of a string if ignoring case otherwise do nothing. This makes SEARCH much faster when case is significant. SEARCH ( sadr slen badr blen -- n f ) Search for the s string inside of the b string. If found f is true and n is the offset from the beginning of the string to where the pattern was found. If not found, f is false and n is meaningless. \ String operators 10Mar84map The following parameters are input to the string operators: sa string-address sl string-length ba buffer-address bl buffer-length ba bl sl DELETE deletes sl characters from the start of the buffer, filling the end with spaces. sa sl ba bl INSERT inserts the minimum of sl or bl characters into ba from sa. sa sl ba bl REPLACE overwrites the minimum of sl or bl characters onto ba from sa. \ Shadows 24Aug86nhm \ Shadow Screen Support 24Aug86nhm DISPLACEMENT offset from a screen to its shadow (>SHADOW) convert screen number in given file to or from its shadow. >SHADOW convert a screen number in FILE to or from its shadow. >IN-SHADOW convert a screen number in IN-FILE to or from its shadow. T Toggle between a screen and its shadow. \ Shadow Screen Support 24Aug86nhm COPY copy a screen and its shadow. CONVEY copy a range of screens and their shadows. \ General Dump Utility 07Feb86nhm .2 Display a 2 digit number followed by a space. EMIT. Emit the character if it is displayable. Otherwise display it as a period. ?.N If the two numbers match, display a downwards pointer, otherwise display the number. ?.A If the two numbers match, display a downwards pointer, otherwise display the number. .HEAD (S -- ) Display the header field of a dump, making it easy to index into the data portion of the display. \ General Dump Utility 07Feb86nhm LDUMP-SEG Segment setup by LDUMP, from which we're dumping D.2 Display a line of 2 digit numbers. DLN (S addr --- ) Dump 16 bytes worth of data starting at the specified address. First the address is displayed, then 2 sets of 8 bytes, followed by the Ascii equivalent. LDUMP (S seg addr len -- ) Dump memory in the range specified. The dump is always in hex, but the current base is unaltered. DUMP (S addr len -- ) Dump memory in the range specified. The dump is always in hex, but the current base is unaltered. \ Inline CASE statement using { and } 25Sep85nhm\ Note: subscripts start with 0 C-ABORT (S arg# -- ) Gives out-of-range error message. (CASE) (S arg# --) Compiled version of inline-case-statement. Next byte compiled will be the address following the last case -- this will be used to determine if arg# is too big or too small (if so, jump to C-ABORT with arg# on stack). If arg# is in range, execute the arg#-th following word, and then skip to the address following the last case. { Compiles (CASE) and leaves space for last-case-address. } Resolves last-case-address for matching { \ ASSOCIATIVE: Table Lookup Def. Word 23JUN83HHL ASSOCIATIVE: An associative memory word. It must be followed by a set of values to be looked up. At Runtime, the values stored in the parameter field are searched for a match. If one if found, the index to that value is returned. If no match is made, then the number of entries, ie max index + 1 is returned. This is the inverse of an array. \ Decompile each type of word 29Sep83map(SEE) Forward reference to decompile deferred words The following are used only by the decompiler: .WORD (S IP -- IP' ) Display the name of a word, and bump the simulated IP by 2. .INLINE (S IP -- IP' ) Display a word that contains an inline literal value. .BRANCH (S IP -- IP' ) Dispaly a word that contains an inline branch. .QUOTE (S IP -- IP' ) Handles the special case of COMPILE xxx. .STRING (S IP -- IP' ) Displays a word with an inline string arguement. \ Decompile each type of word 23JUN83HHLDOES? (S IP -- IP' F ) Increments simulated IP and returns true if call dodoes there.(;CODE) (S IP -- IP' ) Perhaps continue to decompile a defining word. .FINISH (S IP -- IP' ) Display current word and quit. \ Classify each word in a definition 15Mar83mapEXECUTION-CLASS This table lists all of the special cases that must be decompiled differently from ordinary Forth words like DUP and + etc. At runtime, if the simulated IP points to a word in this group, the corresponding index from this table will be returned, and placed upon the stack. If there is no match, then the last index + 1 is returned. \ Classify each word in a definition 23JUN83HHL.EXECUTION-CLASS This giant case statement handles the special case decompiling needed. Each entry corresponds to an entry in the previous EXECUTION-CLASS associative table. The function of each of these words is to decompile the current word that the simulated IP is pointing to, and advance the simulated IP accordingly. If no match in the table, .WORD is used. \ Decompile a : definition 23JUN83HHL.PFA (S CFA -- ) This decompiles a parameter field which contains a list of code fields, as is found in : definitions. .IMMEDIATE (S CFA -- ) This indicates whether the current word is Immediate or not. \ Display category of word 09SEP83HHL.CONSTANT (S CFA -- ) Decompile a Constant, and prints its value. .VARIABLE (S CFA -- ) Decompile a Variable, giving its location and value. .: (S CFA -- ) Decompile a high level : definition. .DOES> (S CFA -- ) Decompile a word defined by a CREATE DOES> word. .USER-VARIABLE (S CFA -- ) Decompile a USER variable, giving the offset from the base of the user area and the current value. \ Display category of word 29Sep83map.DEFER Tell the user that this is a deferred word and decompile its current definition. .USER-DEFER Tell the user that this is a USER deferred word and decompile its current definition. .OTHER (S CFA -- ) This decompiles words whose category was is not known. Code words are recognized, as are words defined by defining words. The runtime portion of a word defined by a defining word is decompiled, since the parameter field is determined by the CREATE portion and cannot be deciphered. If all else fails, the word is listed as UNKNOWN. \ Classify a word based on its CFA 23JUN83HHL DEFINITION-CLASS This categorizes the different classes of words that the decompiler will handle. For each class, determined by the type of defining word used, the code field is identical. Thus the standard classes are recognized. .DEFINITION-CLASS These are the routines that handle the decompilation of each class. The most useful, and of course most common one is .: which decompiles : definitions. If the class is not recognized, we check to see if it is a CODE word or perhaps defined by a high level CREATE DOES> word. \ Top level of the Decompiler SEE 09SEP83HHL((SEE)) (S Cfa -- ) Takes an arbitrary code field address and decompiles it based upon its definition class. Upon completion, it indicates whether or not the word is immediate. SEE (S -- ) The user interface. To decompile something type SEE xxx \ Variables and Setup 10Apr84mapEPSON sets EPSON MX-80 printer to 132 column mode. INIT-PR sets printer to 132 column. Default is EPSON. FOOTING Print a message at the bottom of the page. LOGO The Screen number of your LOGO screen L/PAGE The number of lines per page. PAGE# The current page number as we are printing. PAGE Printer dependent. Get to a new page. Increment the page number and reset the line number and the column number. FORM-FEED Print a form feed character. (PAGE) Print enough linefeeds to get to next page. (SEMIT) send a character to either the printer or the console, but not both. The following words are used only in this utility: SCR#S An array to hold a count and 6 screen numbers. \ Print 2 screens across on a page 09Apr84mapTEXT? (S Scr# -- f ) Given a screen number, returns true if the first character in the screen is printable and the screen is not blank. PR (S scr -- ) Add the screen to the array and increment the pointers. If it is out of range, replace it with the logo screen. 2PR (S Scr1# Scr2# line# -- ) Print the specified line from the two screens given on the stack. The line from scr2 is copied to pad and the line from scr1 is appended, and the result is printed. 2SCR (S Scr1 Scr2 --- ) Print 2 screens across on a page. Calls 2PR on a line by line basis. \ Prints 6 screen on a page 22Feb84mapP-HEADING (S -- ) Prints the heading for each new page. P-FOOTING (S -- ) Prints the footing for each new page. Assumes form feed works \ Prints 6 screen on a page 22Feb84mapPR-START Initialize everything. PR-STOP Resets the deferred word EMIT to send to terminal. PR-PAGE (S -- ) Prints a page worth of screens without shadows. The screens are printed in vertical columns, 6 up on a page. PR-S-PAGE (S -- ) Prints a page worth of screens with shadows. The source code appears in the left column, and the associated shadow on the right column. PR-FLUSH (S -- f ) Fills the SCR#S array if a page is partially filled. Returns true if there is more to print, otherwise false. \ Print Page with Shadows 05Oct83mapSHOW is the used to print a range of screens, from first to last. Screens are printed six to each page. This requires a printer capable of 132 columns per line. Some printers, like the Epson, must be put into a mode where 132 columns per line are available. Blank screens are not printed. SHADOW SHOW is similar, but prints three screens and their three shadows on each page. Typical usage: 1 20 SHOW or 1 20 SHADOW SHOW See the multi-tasker for an example of print spooling. LISTING print entire file, with shadows. 12Oct83map For example, DEBUG WORDS will trace the execution of WORDS the next time it is used. \ Print a High Level Trace 10Mar84mapPut component words in BUG vocabulary. L.ID print the name of a word left justified in a field of least len characters. SLOW when true, step continuously. RES when true, resume debugging. See TRACE. (DEBUG) sets the upper and lower limits of the tracing window to the given values, and patches next. 'UNNEST find end of word to debug. \ Enter and Leave the Debugger 12Oct83mapTRACE is executed every other pass thru NEXT. It displays the contents of the parameter stack and the name of the next word to be executed in the routine being debugged. TRACE then waits for a key unless SLOW is true. If the key is C, F, or Q, special action is taken, otherwise a single step is performed. C turns on continuous running ( and SLOW). F re-enters Forth and interprets commands until RESUME is executed. Q aborts the trace and restores NEXT with FIX. DEBUG patches NEXT to the debugging version of NEXT. DEBUG also sets the upper and lower limits of the tracing region to the ends of the parameter field of the specified word. RESUME turns on RES, which enables tracing to continue.