--------------------------------------------------------------- QL Brouhabouha Forth 1994-05-15 --------------------------------------------------------------- Distribution is welcome, but ONLY allowed with all original textfiles being at least part of what is distributed, and the executable file remains the original one. All rights reserved @ Ewald Pfau, 1991-1994. --------------------------------------------------------------- --------------------------------------------------------------- This is a supplement to file: Brouha.Txt Contents: -- Words and tools not covered by ANS paper -- The block file editor --------------------------------------------------------------- --------------------------------------------------------------- ***************************************************** ** Words not covered by dpANS ** ***************************************************** - Words available in general Forth-Wordlist ------------------- U<=> ( u1 u2 -- -1/0/1) Compare unsigned two values given, return 0 if both are the same, -1 if the value next on stack is smaller than the value on top of stack, 1 otherwise. CASE? ( n1 n2 -- n1 0 // -1) Compare two values given, return -1 if both are the same, elsewise leave the value next on stack and zero on top of stack. UMIN ( u1 u2 -- u3) Leave unsigned the smaller one from two values given. UMAX ( u1 u2 -- u3) Leave unsigned the bigger one from two values given. $CRC16+ ( n0 a n -- n1) Apply a cyclic redundancy check calculation to the string in memory given by its parameters, address and length, starting with the accumulating value given as the next but one value on stack, returning the accumulated value. CREATE-JOB ( #code #data -- a job-id err#) PJOB ( priority job-id -- err#) AJOB ( priority 0/-1 job-id -- err#) SUSJOB ( #ticks job-id -- err#) RELJOB ( job-id -- err#) F#@ ( id -- channel#) Lookup the OS specific channel number of the handle number as it has been returned by OPEN-FILE or by CREATE-FILE. IN-CHANNEL Variable, containing the handle number used for input from keyboard. CRT-CHANNEL Variable, containing the handle number used for output to console. CSIZE PAPER INK CURS-ON DEL ( --) Destructive backspace is output on console window if cursor is not already in first column. SKIP ( a n char -- a+ n-) SCAN ( a n char -- a+ n-) CAPS ( -- a) Address of a variable in which -1 is kept if some system words shall act case independant. These are FIND and SEARCH-WORDLIST for the interpreter as well as COMPARE and SEARCH for string words. Writing 0 to CAPS will switch to case dependant behaviour. CAPITAL ( char -- char) A given character is returned uppercased. STACK| ( ix..iy -- ix..iy // "abcd...|xyz..|") Rearrange the order of values on stack, taking each letter of a first series of letters up to a first pipe sign '|', to be one item on stack in the order as is, the last letter representing the value on top of stack, and rearrange, or as well duplicate or drop, following the series of letters up to a trailing pipe sign. USE ( -- // "name") To the block file system, file is assigned to. This file is opened and the file handle is stored in variable BLOCK-FID. If a block file already has been open with it's file handle stored in BLOCK-FID, it is closed after the new file could be opened. If on the same drive the medium is to be changed, and a file is open on the first medium, so this file should be closed by: " BLOCK-FID @ CLOSE-FILE THROW 0 BLOCK-FID ! ". LOAD-FILE ( n hdl --) A file represented by a file handle is regarded to be a block file, the value stored in BLOCK-FID is saved, the block number given is loaded as with LOAD, and BLOCK-FID restored afterwards. SAVE-FILE ( a n -- err#) An image of the momentary running executable is saved as a file the name of which given by its parameters, address and length. A nonzero value is returned if operation failed. GET-SIZES ( -- #code #data #hdrs) Three values are returned on stack reflecting the amount of memory sizes the executable would claim from the operating system at next startup. These are for maximum size of code, of data, and, as top of stack, of headers. ADJUST-SIZES ( #code #data #hdrs --) Three values are taken from stack to be the sizes of memory which will be claimed from operating system more than momentarily needed, at next start-up of the momentary running executable, if it is saved after adjusting sizes by SAVE-FILE. The values are for additional size of code, of data and of headers area, the last one being expected as top of stack. All parameters being zero will leave an unexpandable execution image which will claim about 100 kB if editor is loaded, about 80 kB without. Data memory already reserved by ALLOCATE is not included and should be added to the parameter for the amount of the size of data area. For use of directory access words OPEN-DIR, READ-DIR, CLOSE-DIR, an amount of 100 address units should be reserved for each instance this will be made use of. Caution! Parameters for an image exceeding available RAM will leave an non-executable image! .MEM ( --) Some values are displayed to reflect the current state of the system, remaining sizes of memory areas, identifiers of wordlists, tasks and heap memory areas. TICKS ( -- n) A value is returned which is incremented once in a second. TICKS>T&D ( n -- ss mm hh dd mm yy) Calculate the values for time and date from the value as given by TICKS. .DATE ( --) The current date is output to the console as given by the OS. .TIME ( --) The current time is output to the console as given by the OS. AVAILABLE ( -- u) Maximum size which may be reserved on the heap by ALLOCATE is returned. ERRORLEVEL ( -- a) - Words available in Assembler wordlist ----------------------- (if assembler loaded or not) >CODES ( -- a) Variable, holds address of a table, in which the execution tokens are kept for all assembler memory and dictionnary accesses. As a default, assembler code is generated in code area. This may be changed by providing a new table containing execution tokens for the actions of C@, @, C!, !, HERE, ALLOT, ALIGN, C, <"C-comma">, and , <"comma">. - Words available in Editor wordlist -------------------------- (if editor loaded or not) B/BLK ( -- 1024) Return size of one block of a block file. BLK-UM* ( u -- d) Multiply a given value with B/BLK, returning a double cell product. BLK/MOD ( d -- mod div) Divide a double cell number by B/BLK, returning modulo and quotient. -SKIP ( a0 n char -- a0 n-) -SCAN ( a0 n char -- a0 n-) WSCAN ( a n1 n2 -- a+ n-) In an array of cells represented by address of first cell and count of cells, a value is scanned for which is given as top of stack. If this value could be found, so the parameters of the rest of the array is returned, starting at the address at which the searched value is stored in and the numbers of cells remaining, including the found position. Elsewise zero is returned as top of stack and the first address behind the array. ?ESC ( -- 1 /key:esc , -1 /cr , 0 , /space = wait) Keyboard is scanned for a keypress. Enter key will return -1, ESC key will return 1, else 0. If space key has been pressed, a second press of space key is waited for. Other keypresses are skipped. TAB+ ( n --) Cursor is positioned to next tab stop for a field width given as parameter. If this field does not fit into the rest of the line, a new line is started. - Debugging --------------------------------------------------- XDUMP ( 'a n --) Show a dump of code memory not addressable with data memory words. 'SEE ( cfa --) Apply the function of SEE on the execution token given instead of the name of a definition. DEBUG ( -- /"name") Debugger is initialized to be called each time, the given will be executed next, if it is a secondary forth definition. Exception handling and QUIT will disable the debugger. Debugger is set to single step mode, so after each step, the Enter key has to be pressed. Instead a line may be given to the interpreter while debugging in single step mode. After execution of this line, the prompt will be the forth prompt with the leading string "debug: ". Next step will be executed if Enter is pressed with an empty commandline. Debugging keys input is taken from keyboard even if input source is a file. Some words used by the debugger itself cannot be debugged, elsewise restrictions for interpreter use while debugging are minimal. With shared code of tasks, only the same instance of code will be debugged, the debugger itself is working in. 'DEBUG ( cfa --) Apply the function of DEBUG on the execution token given instead of the name of a definition. FT ( --) Debugging mode is switched to "Fast Trace". This may be done at any time after the debugger has been initialized. If Enter key is pressed, so mode is switched to single step mode. If space key is pressed, so output is halted until another pressing of the space key. NODEBUG ( --) While in single step debugging mode, debugger is switched off and execution continuos without debugger. - Internal Tasking -------------------------------------------- SELF ( -- a) Within a task, its own task identifier "tcb" is given. PAUSE ( --) Essentially a nope, if tasker is switched off, elsewise a hook, which enables next active task to continue execution until this one by itself executes a PAUSE. Each system word performing I/O ends with the action of PAUSE. TASKER-ON ( --) Behaviour of PAUSE is switched to be a hook into next task in the circular list of current active tasks. TASKER-OFF ( --) Behaviour of PAUSE is switched to be a NOPE. May be executed within tasks instead of semaphores to protect access to open files if used in conjunction with TASKER-ON - the interpreter is switched off also this way, if it is not the current task from where this is executed. WAKE ( tcb --) A task is put into the circular list of current active tasks. SLEEP ( tcb --) A task is taken out from the circular list of current active tasks. If code of a task is placed in the memory area for which a marker has been defined, so the action of SLEEP is performed for this task, if that marker is executed and the task is active. If a task is not an endless loop, so it will stop by performing the action of SLEEP, and re-initialize itself after finishing, for being restartable again by WAKE. RUNS ( tcb -- /"name") To an existing and "sleeping" task, a new action is assigned to, given by . TASK: ( Execution: -- tcb) ( Compilation: #R #S -- /"name") Start of definition of a task . Parameters are to be given for sizes of task own return stack and parameter stack, in address units, should be at least 64 for each of them. HERE and PAD called from within a task will give addresses inside the task. If scratch pad area shall be used inside the task, its size should be taken into account of the size for the parameter stack. - Directory access -------------------------------------------- OPEN-DIR ( a n method -- dir-id err#) Given a string in data memory by its parameters, and the value for a method (which will be ignored), an access will be tried to be opened to a directory on the drive of which the name is contained in the string. An internal identification value and 0 as top of stack will be returned if the operation succeeded, elsewise a value different from 0 as top of stack and a descardable value at next position on stack. NEXT-DIR ( dir-id -- dir-a err#) Given a directory identification as returned by OPEN-DIR, the next entry from the directory on the associated drive is read and the address of a specfic storage area is returned together with 0 if the operation succeeded, elsewise a non-zero value and a discardable value at next position on stack. CLOSE-DIR ( dir-id -- err#) Given a directory identification as returned by OPEN-DIR, all other access to the directory on the associated drive by help of this value is discarded. Temporarilly allocated heap storage area is set free again. >FATTR ( dir-a -- a2) In the specific storage area as given by READ-DIR the address of a character field is calculated, from which a value may be read (by "C@") which should reflect the attribute which the OS stored as associated with the file of which the directory entry just has been read. >FTIME&DATE ( dir-a -- ss mm hh dd mm yy) From the specific storage area as given by READ-DIR, six values for time and date are calculated which are associated with the file to which the just read directory entry belongs to. The values are returned the same way as with forth facility word TIME&DATE, with the values for seconds, minutes, hour, day, month, year on stack, the value for the year of the date being on top of the stack. >FSIZE ( dir-a -- a2) In the specific storage area as given by READ-DIR, the address of a double-cell field is calculated, in which the size of the file may be read (by "2@") of which the directory entry just has been read. After an OPEN-DIR but before a READ-DIR this will give the amount of free memory available on the medium. >FNAME ( dir-a -- a2) In the specific storage area as given by READ-DIR, the address of a counted string is calculated, which holds the name of the file of which the directory entry just has been read. A counted string may be converted to the parameters of a string with address and length by applying COUNT to the address of a counted string as parameter. After an OPEN-DIR but before a READ-DIR this will give the name the medium has been given when it was formatted. DIR ( -- //"name") The directory on a drive is shown of which is given, with names of files, sizes, and asterisks if they are executables. HEADER-READ ( id -- dir-a err#) QDOS Header information of an open file is read into an area starting at "dir-a". Tools for queries from directory entries may be applied; information for file-size is mapped as a double-cell value. HEADER-WRITE ( id -- err#) QDOS Header information of an open file is written back using "dir-a" as obtained by HEADER-READ. If header information for data allocation is to be changed, the adequate value should be written as a single cell value into offset 6 of "dir-a" with "!". If header information for file access is to be changed, the adequate value (1 for an executable, 0 for a data file) should be written into offset 5 of "dir-a" as a character value with "C!". --------------------------------------------------------------- --------------------------------------------------------------- *************************************************************** ** Block File Editor ** *************************************************************** Before editing, first a block file has to be assigned to be the default block file for the interpreter, using USE . If while editing more files have been opened, so the last one edited will be the one which is assigned to be the default block file after leaving the editor. By envoking the editor, an "ID" is asked for, holding two characters; this will be put into the top line of each changed block while editing, if this line was not empty. The ID is put together with current date in the form "ddmmmyyid" right justified. If the ID query is skipped by only hitting the enter-key, so no ID's will be written. If an ID is active, the query is skipped. Pushed lines and find-strings are preserved if the editor is left and entered again. By entering the editor, state of the debugger and values on the stack remain untouched except for the case of read/write/open failures. Cut&Paste between files may be done either by Push&Pop for lines, or by setting markers as "from" and "up to" for blocks, then switching to target file, then "copy marked blocks" and "delete marked blocks". There should be no restriction on size of copied areas other than dictated by the medium. Files will be resized, cut (if TK2 is workable) or enlargened as necessary. The functions for insertion of one block or deletion of current block only work if dummy markers are set. Deletion of current block will leave the last block of the file empty. Insertion first will use an empty last block, before enlargening the file. By using a block file with a size smaller than 1024 bytes, that is less than one full block, this block probably is filled with 0's instead of with blanks - following the default behaviour of the block cache system of the interpreter. These lines should be deleted and the file should be flushed then, so the size is reset to be 1024 bytes. Insertion of one block after that only will work then, if this "block 0" is not left empty (that is: at least a backslash as first character in first line may be written). Block 0 never will be taken as input for the interpreter, it is always a comment block. Block 1 for usual is the block containing loading instructions for random access into the file. ED ( --) Start editing with the block of which the number is held in variable SCR. By default this is 1, at start-up this is 0, elsewise the number of the last block edited. EDIT ( blk --) Start editing with the block of which the number is given as a parameter. ID-OFF ( --) Cancel a previously put-in ID. ALL-FLUSH ( --) Flush all files open for the editor from within the interpreter. ALL-CLOSE Close all files open for the editor except the one last edited, which is the default block file for the interpreter. The following keys are assigned to: (A=ALT, S=Shift, ^=CTRL) **** Handle cursor ************ jump: left right column A-left A-right start/end of line S-left S-right word up down row S-up S-down top/bottom of screen Tab S-Tab +/- 8 columns Enter next line, 1st column **** Handle chars ************* ^left ^right delete ^H delete ^Q toggle mode for insert/overwrite **** Handle lines ************* ^N insert ^Y delete ^Z delete ^O clear-EOL ^S split ^M join if next line fits F3 push (buffer may hold 32 lines) F4 push© F5 pop if line fits **** Handle screens *********** ^up page back ^down page ahead A-up page back A-down page ahead S-A-up 1st screen of file S-A-down last screen of file S-F5 "shadow" screen - toggle half of file-size back/ahead ^U undo if updated ^D delete current screen if marker set (ignore marker) ^T insert one screen if marker set (ignore marker) **** Find/Replace ************* F2 S-F2 input & find ahead / backwards ^L ^K find next / previous ( not implemented, but reserved keys: ) ( ^R ^E find&replace next / previous) **** Handle markers *********** F1 goto A-F1 set A-F2 reset A-F3 copy marked blocks A-F4 delete marked blocks **** Handle files ************* ^F3 open ^F4 close S-F3 swap S-F4 roll ^F flush all open files ^B make a backup **** Leave editor ************* ESC modified & flushed ^X unmodified if updated --------------------------------------------------------------- ---------------------------------------------------------------