Preface

The original QL Toolkit was produced in something of a rush to provide useful facilities which, arguably, should have been built in to the QL to start with. Since its appearance, I have been subjected to continuous pressure to modify certain facilities and extend the range of facilities provided.

QLToolkit II is, therefore, a revised (to the extent of being almost completely rewritten) and much enlarged version of the original QL Toolkit. Old facilities now work faster and are more compact, so that there is room in the ROM cartridge for over 100 operations.

The fact that QLToolkit II ever saw the light of day is due to prompting from a number of quarters. Many people have contacted me complaining that they have been unable to lay their hands on the original QLToolkit, and this eventually convinced me that there was a market for a second version. Repeated criticism of the original facilities made at great length (and with justification) by Chas Dillon have provided the basis for many of the modifications to the old routines. Ed Bruley has provided invaluable practical support in putting the product on the market, and Cambridge Systems Technology allowed me to use one of their Winchester disk systems to test the network server.

Even so, QLToolkit II might not have been completed without the unrelenting encouragement from Hellmuth Stuven of QSOFT, Denmark, whose indomitable faith in the technical merit of this product has kept me on my toes.

My thanks to you all, TT.

1  Introduction

QJUMP Toolkit II for the QL

Version II of the QJUMP Toolkit for the QL is an extended and improved version of the original QL Toolkit. This new version is largely rewritten to provide more facilities and to make the existing facilities of the QL and the QL Toolkit more powerful. Since many of these improvements are to correct defects in the ROMs supplied with the QL, it would be better to supply an upgrade to the QL by replacing the Sinclair ROMs. Given the hostile attitude of Sinclair Research Limited towards such an upgrade, this Toolkit II is supplied as the next best thing.

The Toolkit II attempts to put a large number of facilities into a consistent form. A little preamble is worthwhile to explain some of the principles.

This manual uses the following simple convention when describing commands and function calls:

- CAPITAL LETTERS are used for parts typed as is

- bold letters are used descriptively

- lower case letters are used as examples

Thus

- VIEW name is a description

- VIEW fred is an example

1.1 Commands Procedures Functions

The extensions to SuperBASIC appear as extra commands, procedures and functions. The distinction between a command and a procedure is very slight and the two terms tend to be used interchangeably: the command is what a user types, the procedure is what does the work. In some cases a command is used to invoke a procedure which in turn sets up and initiates a Job (e.g. SPL starts the resident spooler). A function is something that has a value and the name of a function cannot be used as a command: the value may be PRINTED, used in an expression or assigned to a variable.

1.2 Y/N/A/Q?

Y/N/A/Q? is a concise, if initially confusing, prompt that Toolkit II is bound to throw at the unsuspecting user from time to time. It is no more than a request for the user to press one of the keys Y (for yes), N (for no), A (for all) or Q (for Oh! Bother, I give up). What will actually happen when you press one of these keys, will depend on what you are trying to do at the time.

There is a short form which only allows Y (for yes) and N (for no).

Before the reply to the Y/N/A/Q? (or Y or N?) prompt is read, any characters which have been typed ahead are discarded. Typing BREAK (CTRL + space) or ESC will have the same effect as a 'Q' (or 'N') keypress.

1.3 Overwriting

In some cases a command is given to create a new file with the same name as a file which already exists. In general this will result not in an error message, but a prompt requesting permission to overwrite the file. There are two (deliberate) exceptions to this rule: OPEN_NEW will return an error, while the procedures COPY_O, SAVE_O, SBYTES_O and SEXEC_O and the spooler will happily overwrite their destination files without so much as a 'by your leave'.

1.4 #channel

All input and output from SuperBASIC is through 'channels'. Some of these channels are implicit and are never seen (e.g. the command 'SAVE SER' opens a channel to SER, lists the program to the channel, and closes the channel). Others are identified by a channel number which is a small, positive, integer preceded by a '#' (e.g. #2).

Many commands either allow or require a channel to be specified for input or output. This should be a SuperBASIC channel number:

- #0 is the command channel (at the bottom of the screen),

- #1 is the normal output channel and

- #2 is the program listing channel.

Other channels (e.g. for communication with a file) may be opened using the SuperBASIC OPEN commands (see section 10).

For interactive commands the default channel is #0, for most other commands the default channel is #1, for LIST and ED the default channel is #2, while for file access commands the default is #3.

For many of the commands it is possible to specify an implicit channel. This is in the form of '\' followed by a file or device name. The effect of this is to open an implicit channel to the file or device, do the required operation and close the channel again.

e.g.

DIR

list current directory to #1

DIR #2

list current directory to #2

DIR \files

list current directory to file 'files'

this last example should be distinguished from

DIR files

list directory entries starting with files to #1

1.5  File and Device Names

In general it is possible to specify file or device names as either a normal SuperBASIC name or as a string. The syntax of SuperBASIC names limits the characters used in a name to letters digits and the underscore. There is no such limitation on characters used in a string. On a standard QL, a filename has to be given in full, but using the Toolkit II, the directory part of the name can be defaulted and just the filename used.

e.g.

OPEN #3,fred

open file fred in the current directory

This gives rise to one problem: the SuperBASIC interpreter has the unfortunate characteristic of trying to evaluate all the parameters of a command as expressions; in this example 'fred' will probably be an undefined variable which should not give rise to any problems. However, the command

OPEN #3,list

will give an 'error in expression' error as it is not possible for 'LIST', which is a command, to have a value. There are two ways around this problem: either avoid filenames which are the same as commands (procedures), functions or SuperBASIC keywords (e.g. FOR, END, IF etc.), or put the name within quotes as a string:

OPEN #3,'list'

or OPEN #3,"list"

1.6  CTRL F5

The CTRL F5 keystroke (press CTRL and while holding it down press F5) is used to freeze the QL screen. Many commands in Toolkit II check their output window and, when it is full, internally generate a CTRL F5 keystroke to hold the display until the user presses a key. (F5 will usually be the best key to press.)

2 Contents of Toolkit II

SuperBASIC is used as a command language on the QL as well as a programming language. Extensions are provided to improve the facilities of SuperBASIC in both these areas as well as providing program development facilities.

The following list gives a comprehensive form of each command or function. There are often default values of the parameters to simplify the use of the procedures.

2.1  Development Facilities

Section 3  File editing

Toolkit II provides an editor and a command for viewing the contents of text files. ED is a window based editor for editing SuperBASIC programs. VIEW is a command for examining line based files (e.g. assembler source files).

Commands:

ED #channel, line number

edit SuperBASIC program

VIEW #channel, name

view contents of a file

2.2  Command Language

The command language facilities of Toolkit II are intended to provide the QL with the control facilities to unlock the potential of the QDOS operating system. Most of these are 'direct' commands: they are typed in and acted on immediately. This does not mean that they may not be used in programs, but some care should be taken when doing this.

Section 4  Directory Control

QDOS does have a tree directory structure filing system! The Toolkit II provides a comprehensive set of facilities for controlling access to directories within this tree.

Commands:

DATA_USE name

set the default directory for data files

PROG_USE name

set the default directory for executable programs

DEST_USE name

set the default destination directory (COPY, WCOPY)

SPL_USE name

set the default destination device (SPL)

DDOWN name

move to a sub-directory

DUP

move up through the tree

DNEXT name

move to another directory at the same level

DLIST #channel

lists the defaults

Functions:

DATAD$

function to find current data directory

PROGD$

function to find current program directory

DESTD$

function to find current default destination

Section 5   File Maintenance

All the filing system maintenance commands use the default (usually 'data') directories. Some of the commands are interactive and thus not suitable for use in SuperBASIC programs: these are marked with an asterisk in this list. In these cases there are also simpler commands which may be used in programs. Depending on the command, the name given may be a generic (or 'wildcard') name referring to more than one file. With the exception of DIR (an extended version of the standard QL command DIR), all of these 'wildcard' commands have names starting with 'W'.

Commands:

DIR #channel, name

drive statistics and list of files

WDIR #channel, name

list of files

STAT #channel, name

drive statistics

WSTAT #channel, name

list of files and their statistics

DELETE name

delete a file

*WDEL #channel, name

delete files

COPY name TO name

copy a file

COPY_O name TO name

copy a file (overwriting)

COPY_N name TO name

copy a file (without header)

COPY_H name TO name

copy a file (with header)

*WCOPY #channel, name TO name

copy files

SPL name TO name

spool a file

SPLF name TO name

spool a file, <FF> at end

RENAME name TO name

rename a file

*WREN #channel, name TO name

rename files

Section 6  SuperBASIC Programs

Toolkit II redefines and extends the file loading and saving operations of the QL. All the commands use the default directories. Additionally, the execution control commands have been extended to cater for the error handling functions of the 'JS' and 'MG' ROMs.

Commands:

DO name

do commands in file

LOAD name

load a SuperBASIC program

LRUN name

load and run a SuperBASIC program

MERGE name

merge a SuperBASIC program

MRUN name

merge and run a SuperBASIC program

SAVE name, ranges

save a SuperBASIC program

SAVE_O name, ranges

as SAVE but overwrites file if it exists

RUN line number

start a SuperBASIC program

STOP

stop a SuperBASIC program

NEW

reset SuperBASIC

CLEAR

clear SuperBASIC variables

Section 7  Load and Save

The binary load and save operations of the QL are extended to use the default directories.

Commands:

LRESPR name

load a file into resident procedure area and CALL

LBYTES name, address

load a file into memory at specified address

CALL address, parameters

CALL machine code with parameters

SBYTES name, address, size

save an area of memory

SBYTES_O name, address, size

as SBYTES but overwrites file if it exists

SEXEC name, address, size, data

save an area of memory as an executable file

SEXEC_O name, address, size, data

as SEXEC but overwrites file if it exists

Section 8  Program Execution

Program execution is, Anne Boleyn would be relieved to know, the opposite of program (ex)termination. The EXEC and EXEC_W commands in the  standard QL are replaced by EX and EW in the QL Toolkit. Toolkit II redefines EXEC and EXEC_W to be the same as EX and EW. ET is for debuggers (no offence meant) only.

Commands:

EXEC/EX program specifications

load and set up one or more executable files

EXEC_W/EW program specifications

ET program specifications

Section 9  Job Control

The multitasking facilities of QDOS are made accessible by the job control commands and functions of Toolkit II.

Commands:

JOBS #channel

list current jobs

RJOB id or name, error code

remove a job

SPJOB id or name, priority

set job priority

AJOB id or name, priority

activate a job

Functions:

PJOB (id or name)

find priority of job

OJOB (id or name)

find owner of job

JOB$ (id or name)

find job name!

NXJOB (id or name,id)

find next job in tree

2.3  SuperBASIC programming

Toolkit II has extensions to SuperBASIC to assist in writing more powerful and flexible programs. The major improvements are in file handling and formatting.

Section 10  Open and Close

The standard QL channel OPEN commands are redefined by Toolkit II to use the data directory. In addition, Toolkit II provides a set of functions for opening files either using a specified channel number (as in the standard QL commands), or they will find and return a vacant channel number. The functions also allow filing system errors to be intercepted and processed by SuperBASIC programs.

Commands:

OPEN #channel, name

open a file for read/write

OPEN_IN #channel, name

open a file for input only

OPEN_NEW #channel, name

open a new file

OPEN_OVER #channel, name

open a new file, if it exists it is overwritten

OPEN_DIR #channel, name

open a directory

CLOSE #channels

close channels

Functions:

FTEST (name)

test status of file

FOPEN (#channel, name)

open a file for read/write

FOP_IN (#channel, name)

open a file for input only

FOP_NEW (#channel, name)

open a new file

FOP_OVER (#channel, name)

open a new file, if it exists it is overwritten

FOP_DIR (#channel, name)

open a directory

Section 11  File Information

Toolkit II has a set of functions to read information from the header of a file.

FLEN (#channel)

find file length

FTYP (#channel)

find file type

FDAT (#channel)

find file data space

FXTRA (#channel)

find file extra info

FNAME$ (#channel)

find filename

FUPDT (#channel)

find file update date

Section 12  Direct Access Files

Toolkit II has a set of commands for transferring data to and from any part of a file. The commands themselves read or write 'raw' data, either in the form of individual bytes, or in SuperBASIC internal format (integer, floating point or string).

Commands:

BGET #channel\position, items

get bytes from a file

BPUT #channel\position, items

put bytes onto a file

GET #channel\position, items

get internal format data from a file

PUT #channel\position, items

put internal format data onto a file

TRUNCATE #channel\position

truncate file

FLUSH #channel

flush file buffers

Functions:

FPOS (#channel)

find file position

Section 13  Format Conversions

Toolkit II provides a number of facilities for fixed format I/O. These include binary and hexadecimal conversions as well as fixed format decimal.

Commands:

PRINT_USING #channel, format,

fixed format output list of items to print

Functions:

FDEC$ (value, field, ndp)

fixed format decimal

IDEC$ (value, field, ndp)

scaled fixed format

CDEC$ (value, field, ndp)

decimal

FEXP$ (value, field, ndp)

fixed exponent format

HEX$ (value, number of bits)

convert to hexadecimal

BIN$ (value, number of bits)

convert to binary

HEX (hexadecimal string)

hexadecimal to value

BIN (binary string)

binary to value

Section 14  Display Control

Toolkit II provides commands for enabling and disabling the cursor as well as setting the character fount and sizes or restoring the windows to their turn on state.

Commands:

CURSEN #channel

enable the cursor

CURDIS #channel

disable the cursor

CHAR_USE #channel, addr1, addr2

set or reset the character fount

CHAR_INC #channel, x inc, y inc

set the character x and y increments

WMON mode

reset to 'Monitor'

WTV mode

reset to 'TV' windows

Section 15  Memory Management

Toolkit II has a set of commands and functions to provide memory management facilities within the 'common heap' area of the QL.

Functions:

FREE_MEM

find the amount of free memory

ALCHP (number of bytes)

allocates space in common heap (returns the base address of the space)

Commands:

RECHP base address

return space to common heap

CLCHP

clear out all allocations in the common heap

DEL_DEFB

delete file definition blocks from common heap

Section 16 Procedure Parameters

Four functions are  provided by Toolkit II to improve the handling of procedure (and function) parameters. Using these it is possible to determine the type (integer, floating point or string) and usage (single value or array) of the calling parameter as well as the 'name'.

PARTYP (name)

find type of parameter

PARUSE (name)

find usage of parameter

PARNAM$ (parameter number)

find name of parameter

PARSTR$ (name, parameter number)

if parameter 'name' is a string, find the value, else find the name.

Section 17  Error Handling

These facilities are provided for error processing in versions JS and MG of SuperBASIC.

ERR_DF

true if drive full error has occurred

REPORT #channel, error number

report an error

CONTINUE line number

RETRY line number

continue or retry from a specified line

Section 18  Time-keeping

Two clocks are provided in Toolkit II, one configurable digital clock, and an alarm clock.

CLOCK #channel, format

variable format clock

ALARM hours, minutes

alarm clock

Section 19  Extras

EXTRAS

lists the extra facilities linked into SuperBASIC

TK2_EXT

enforces the Toolkit II definitions of common commands and functions

2.4  Extensions to Devices

In addition to extending the SuperBASIC interpreter, Toolkit II has important extensions to the console, Microdrive and Network device drivers.

Section 20  Console Driver

Toolkit II provides last line recall for the command channel #0 as well as allowing strings of characters to be assigned to 'ALT' keystrokes received on this channel.

Commands:

<ALT><ENTER>

keystroke recovers last line typed

ALTKEY character, strings

assign a string to <ALT> character keystroke

Section 21  Microdrive Driver

Toolkit II extends the microdrive driver to provide OPEN file with overwrite, as well as TRUNCATE and RENAME of files. These facilities are supported at QDOS level (Traps #2 and #3) as well as from SuperBASIC. The FLUSH operation is respecified to set the file header as well as flush the buffers.

Section 22  Network Driver

The network driver is enhanced to provide a primitive form of broadcast communication as well as providing a comprehensive file server program which allow many QLs to share a disk system or printer.

Commands:

FSERVE

invokes the 'file server'

NFS_USE name, network names

sets the network file server name

Device names:

Nstation number_IO device          the name of a remote IO device (e.g. N2_FLP1_ is floppy 1 on network station 2)

3  File Editing

3.1  ED - SuperBASIC Editor

ED is a small editor for SuperBASIC programs which are already loaded into the QL. If the facilities look rather simple and limited, please remember that the main design requirement of ED is the small size to leave room for other facilities.

ED is invoked by typing:

ED

or ED line number

or ED #channel number

or ED #channel number, line number

If no line number is given, the first part of the program is listed, otherwise the listing in the window will start at or after the given line number. If no channel number is given, the listing will appear in the normal SuperBASIC edit window #2. If a window is given, then it must be a CONsole window, otherwise a 'bad parameter' error will be returned. The editor will use the current ink and paper colours for normal listing, while using white ink on black paper (or vice versa if the paper is already black or blue) for 'highlighting'. Please avoid using window #0 for the ED.

The editor makes full use of its window. Within its window, it attempts to display complete lines. If these lines are too long to fit within the width of the window, they are 'wrapped around' to the next row in the window: these extra rows are indented to make this 'wrap around' clear. For ease of use, however, the widest possible window should be used.

ED must not be called from within a SuperBASIC program.

The ESC key is used to return to the SuperBASIC command mode.

After ED is invoked, the cursor in the edit window may be moved using the arrow keys to select the line to be changed. In addition the up and down keys may be used with the ALT key (press the ALT key and while holding it down, press the up or down key) to scroll the window while keeping the cursor in the same place, and the up and down keys may be used with the SHIFT key to scroll through the program a 'page' at a time.

The editor has two modes of operation: insert and overwrite. To change between the two modes use 'CTRL F4' (press CTRL and while holding it down press F4). There is no difference between the modes when adding characters to or deleting characters from the end of a line. Within a line, however, insert mode implies that the right hand end of a line will be moved to the right when a character is inserted, and to the left when a character is deleted. No part of the line is moved in overwrite mode. Trailing spaces at the end of a line are removed automatically.

To insert a new line anywhere in the program, press ENTER. If there is no room between the line the cursor is on and the next line in the program (e.g the cursor is on line 100 and the next line is 101) then the ENTER key will be ignored, otherwise a space is opened up below the current line, and a new line number is generated. If there is a difference of 20 or more between the current line number and the next line number, the new line number will be 10 on from the current line number, otherwise, the new line number will be half way between them.

If a change is made to a line, the line is highlighted: this indicates that the line has been extracted from the program. The editor will only replace the line in the program when ENTER is pressed, the cursor is moved away from the line, or the window is scrolled. If the line is acceptable to SuperBASIC, it is rewritten without highlighting. If, however, there are syntax errors, the message 'bad line' is sent to window #0, and the line remains highlighted.

While a line is highlighted, ESC may be used to restore the original copy of the line, ignoring all changes made to that line.

If a line number is changed, the old line remains and the new line is inserted in the correct place in the program. This can be used to copy single lines from one part of the program to another.

If all the visible characters in a line are deleted, or if all but the line number is deleted, then the line will be deleted from the program. An easier way to delete a line is to press CTRL and ALT and then the left arrow as well.

The length of lines is limited to about 32766 bytes. Any attempt to edit longer lines may cause undesirable side effects. If the length of a line is increased when it is changed, there may be a brief pause while SuperBASIC moves its working space.

3.2  Summary of Edit Operations

The general usage of the keys follows the Concepts section of the QL User Guide first, and then the business programs usage.

TAB                   tab right (columns of 8)

SHIFT TAB             tab left (columns of 8)

ENTER                 accept line and create a new line

ESC                   escape - undo changes or return to SuperBASIC

up arrow              move cursor up a line

down arrow            move cursor down a line

ALT up arrow          scroll up a line (the screen moves down!)

ALT down arrow        scroll down a line (the screen moves up!)

SHIFT up arrow        scroll up one page

SHIFT down arrow      scroll down one page

left arrow            move cursor left one character

right arrow           move cursor right one character

CTRL left arrow       delete character to left of cursor

CTRL right arrow      delete character under cursor

CTRL ALT left arrow   delete line

SHIFT F4              change between overwrite and insert mode

3.3  Viewing a file

VIEW is procedure intended to allow a file to be examined in a window on the QL display. The default window is #1.

View is invoked by typing

VIEW name               View file 'name' in window #1

VIEW #channel, name     View file 'name' in given window

VIEW \name1, name2      Send file 'name2' to 'name1'

VIEW truncates lines to fit the width of the window. When the window is full, CTRL F5 is generated. If the output device (or file) is not a console, then lines are truncated to 80 characters.

4  Directory Control

4.1  Directory Structures

In QDOS terminology, a 'directory' is where the system expects to find a file. This can be as simple as the name of a device (e.g. MDV2_ the name of the Microdrive number 2) or be much more complex forming part of a 'directory tree' (directories grow on trees - honestly, they do). For example: the directory MDV2_ could include directories JOHN_ and OLD_ (note: all directory names end with an '_'), and JOHN_ could include files DATA1 and TEST).

MDV2_

___________I__________

I              I

JOHN_           OLD_

_______I_________

I         I

DATA1      TEST

This shows another characteristic of the 'directory tree': it grows downwards. The complete QDOS filename for DATA1 in this example is MDV1_JOHN_DATA1. (You may have come across the terms 'pathname' or 'treename': these refer to the same thing as a QDOS filename.)

One unusual characteristic of the QDOS directory structure is the absence of a formal file name 'extension'. This is not strictly necessary as 'extensions' (e.g. _aba for ABACUS files, _asm for assembler source files etc.) are treated as files within a directory.

This can be illustrated with the case of an assembler program TEST, processed using the GST macro assembler and linkage editor. The assembler source file (TEST_ASM), the listing output from the assembler (TEST_LIST), the relocatable output from the assembler (TEST_REL), the linker control file (TEST_LINK), the linker listing output (TEST_MAP) and the executable program produced by the linker (TEST_BIN) are all treated as files within the directory TEST_.

MDV2_

________I______

I

JOHN_

___________________I________________

I

TEST_

__________________I_________________

I       I       I      I      I      I

ASM     LIST    REL    LINK   MAP    BIN

This Toolkit provides facilities to set default directories. The defaults are available for all filing system operations. A default may be set to any level of complexity and gives a starting point for finding a file in the tree structure. Thus, in this example, if the default is MDV2_, then JOHN_TEST_ASM will find the assembler source. If the default is MDV2_JOHN_, then TEST_ASM will find it, while the full filename MDV2_JOHN_TEST_ASM will find the file regardless of the default.

4.2  Setting Defaults

Unusually, the Toolkit extensions to QDOS support three distinct defaults for the directory structure. This is because QDOS is an intrinsically multi-drive operating system. It is expected that executable programs will be in a different directory, and probably on a different drive, from any data files being manipulated. Furthermore, the copying procedures are more likely to be used to copy from one directory to another, or from the filing system to a printer or other output device, than they are to be used to copy files within a directory.

There are three commands for setting the three defaults:

DATA_USE directory name            set data default

PROG_USE directory name            set program default

DEST_USE directory name            set destination default

If the directory name supplied does not end with '_', '_' will be appended to the directory name.

The DATA_USE default is used for most filing system commands in the Toolkit. The PROG_USE default is used only for finding the program files for the EX/EXEC commands, while the DEST_USE default is used to find the destination filename when the file copying and renaming commands (SPL, COPY, RENAME etc.) are used with only one filename.

There is a special form of the DEST_USE command which does not append '_' to the name given. Notionally this provides the default destination device for the spooler:

SPL_USE device name

This sets the destination default, but, if there is no '_' at the end, it is not treated as a directory and so, if a destination filename is required, the default will be used unmodified.

E.g.    DEST_USE flp2_old               (default is FLP2_OLD_)

.....

SPL fred

or SPL_USE flp2_old_               (default is FLP2_OLD_)

.....

SPL fred

Both of these examples will spool FRED to FLP2_OLD_FRED. Whereas if SPL_USE is used with a name without a trailing '_' (i.e. not  a directory name) as follows

SPL_USE ser                     (default is SER)

.....

SPL fred

then FRED will be spooled to SER (not SER_FRED).

Note that SPL_USE overwrites the DEST_USE default and vice versa

4.3  Directory Navigation

Three commands are provided to move through a directory tree.

DDOWN name                 move down (append 'name' to the default)

DUP                        move up (strip off the last level of the directory)

DNEXT name                 move up and then down a different branch of the tree

It is not possible to move up beyond the drive name using the DUP command. At no time is the default name length allowed to exceed 32 characters.

These commands operate on the data default directory. Under certain conditions they may operate on the other defaults as well:

- If the progam default is the same as the data default, then the two defaults are linked and these commands will operate on the PROG_USE default as well.

- If the destination default ends with '_' (i.e. it is a default directory rather than a default device), then these commands will operate on the destination default.

These rules are best seen in action:

data        program     destination

initial values          mdv2_       mdv1_       ser

DDOWN john              mdv2_john_  mdv1_       ser

DNEXT fred              mdv2_fred_  mdv1_       ser

PROG_USE mdv2_fred      mdv2_fred_  mdv2_fred_  ser

DNEXT john              mdv2_john_  mdv2_john_  ser

DUP                     mdv2_       mdv2_       ser

DEST_USE mdv1           mdv2_       mdv2_       mdv1_

DDOWN john              mdv2_john_  mdv2_john_  mdv1_john_

SPL_USE ser1c           mdv2_john_  mdv2_john_  ser1c

4.4  Taking Bearings

Should you wonder where you are in the directory tree, there is a command to list all three defaults:

DLIST                      list data, program and destination defaults

or DLIST #channel

or DLIST \name

If an output channel is not given, the defaults are listed in window #1.

To find the defaults from within a SuperBASIC program there are three functions:

DATAD$                     find the data default

PROGD$                     find the program default

DESTD$                     find the destination default

The functions to find the individual defaults should be used without any parameters. E.g.

IF DATAD$<>PROGD$: PRINT 'Separate directories'

DEST$=DESTD$

IF DEST$ (LEN (DEST$))='_': PRINT 'Destination'! DEST$

Facilities to enable executable programs to find the default directories were provided in the original Sinclair QL Toolkit, and the same facilities are provided in this Toolkit. These facilities are not widely used in commercial software for the QL. The real solution of providing the default directories at QDOS trap level can only be attained using additional hardware in the expansion slot or by replacement operating system ROMs. You will probably find, therefore, that much commercially written software will not recognise the defaults you have set. There is an example of overcoming this problem in the example program appendix.

5  File Maintenance

The standard file maintenance procedures of the QL (COPY, DELETE and DIR) are filled out into a comprehensive set in Toolkit II. All of the commands, both standard and new, use the directory defaults; in addition, many of the commands use wild card names to refer to groups of similarly named files.

5.1  Wild Card Names

A wild card name is a special type of filename where part of the name is treated as a 'wild card' which can be substituted by any string of characters. If, for convenience, the wild card name is to be a normal SuperBASIC name, then special characters cannot be used for the wild card (e.g. myfiles_*_asm would be treated by SuperBASIC as an arithmetic expression and SuperBASIC would attempt to multiply myfiles_ by _asm). For this reason a simpler scheme is adopted: any missing section of a file name is treated as a wild card. The end of a wild card name is implicitly missing.

If the wild card name is not a full file name, the default directory is added to the start of the name.

In the following example, the default directory is assumed to be FLP2_.

Wild card name  Full wild card name     Typical matching files

fred            flp2_fred               flp2_fred

flp2_freda_list

_fred           flp2__fred              flp2_fred

flp2_freda_list

flp2_old_fred

flp2_old_freda_list

flp1_old__list  flp1_old__list          flp1_old_jo_list

flp1_old_freda_list

5.2  Directory Listing

There are two forms of directory listing: the first lists just the filenames, the second lists the filenames together with file size and update date. All the commands use wild card names and the data default directory. The output from these commands will be sent to channel #1 by default; but a channel or implicit channel may be specified: if the output channel is to a window the listing is halted (CTRL F5) when the window is full.

DIR #channel, name                 drive statistics and list of files

WDIR #channel, name                list of files

WSTAT #channel, name               list of files and their statistics

In all cases the channel specification and the name are optional.

The possible forms of (for example) WDIR are

WDIR                       list current directory to #1

or WDIR #channel              list current directory to #channel

or WDIR \name                 list current directory to 'name'

or WDIR name                  list directory 'name' to #1

or WDIR #channel, name        list directory 'name' to #channel

or WDIR \name1, name2         list directory 'name2' to 'name1'

E.g.

WDIR \ser, _asm            list all _asm files in current directory to SER

WDIR flp1_                 list all files on FLP1_ in window #1

WDIR #3                    list all files in current directory to channel #3

DIR is provided for compatibility only: before listing the files, the drive statistics (medium name, number of vacant sectors / number of good sectors) are written out.

5.3  Drive Statistics

There is one command to print the statistics for the drive holding a specified directory, or the data default directory.

STAT #channel, name

or STAT \name1, name2

Both the channel and the name are optional.

5.4  File Deletion

The standard procedure DELETE has been modified to use the data default directory unless a full file name is supplied. No error is generated if the file is not found. There are also two interactive commands to delete many files using wild card names.

DELETE name                        delete one file

WDEL #channel, name                delete files

For WDEL both the channel and the name are optional.

E.g.

WDEL                       delete files from current directory

WDEL _list                 delete all _list files from current directory

Unless a channel is specified, the wild card deletion procedures use the command window #0 to request confirmation of deletion. There are four possible replies:

Y       (yes)  delete this file

N       (no)   do not delete this file

A       (all)  delete this and all the next matching files

Q       (quit) do not delete this or any of the next files

5.5  File Copying

The two forms of the COPY command  provided with the QL are changed to use default filenames, and also to provide more flexibility. A number of other commands are added.

Files in QDOS have headers which provide useful information about the file that follows. It depends on the circumstances whether it is a good idea to copy the header of a file when the file is copied.

It is a good idea to copy the header when:

a) copying an executable program file so that the additional file information is preserved,

b) copying a file over a pure byte serial link so that the communications software will know in advance the length of the file.

It is a bad idea to copy the header when:

c) copying a text file to a printer because the header will be likely to have control codes and spurious or unprintable characters.

The general rules used by the COPY procedures in Toolkit II, are that the header is only copied if there is additional information in the header. This caters for cases (a) and (c) above. A COPY_N command is included for compatibility with the standard QL COPY_N: this never copies the header. A COPY_H command is included to copy a file with the header to cater for case (b) above. (Note that the standard QL command COPY always copies the header.) Neither COPY_N nor COPY_H need ever be used for file to file copying.

A second general rule used by the COPY (as well as by the WREN) procedures is that if the destination file already exists, then the user will be asked to confirm that overwriting the old file is acceptable. The COPY_O (copy overwrite) and the spooler procedures do not extend this courtesy to the user.

If the commands are given with two filenames then the data default directory is used for both files. If, however, only one filename (or, in the case of the wild card procedures, no name at all) is given then the destination will be derived from the destination default:

a) if the destination default is a directory (ending with '_', set by DEST_USE) then the destination file is the destination default followed by the name,

b) if the destination default is a device (not ending with '_', set by SPL_USE) then the destination is the destination default unmodified.

5.5.1 Single File Copies

COPY name TO name                  copy a file

COPY_O name TO name                copy a file (overwriting)

COPY_N name TO name                copy a file (without header)

COPY_H name TO name                copy a file (with header)

These commands can be given with one or two names. The separator 'TO' is used for clarity, you may use a comma instead.

To illustrate the use of the copy command, assume that the data default is MDV2_ and the destination default is MDV1_.

COPY fred TO old_fred              copies mdv2_fred to mdv2_old_fred

COPY fred, ser                     copies mdv2_fred to ser

COPY fred                          copies mdv2_fred to mdv1_fred

SPL_USE ser

....

COPY fred                          copies mdv2_fred to ser

5.5.2 Wild Card Copies

The interactive copying procedure WCOPY is used for copying all or selected parts of directories. The command may be given with both source and destination wild card names, with one wild card name or with no wild card names at all. Giving the command with no wild card names has the same effect as giving one null name:

WCOPY      and     WCOPY ''        are the same.

If you get confused by the following rules about the derivation of the copy destination, just use WCOPY intuitively and look carefully at the prompts.

If the destination is not the destination default device, then the actual destination file name for each copy operation is made up from the actual source file name and the destination wild name. If a missing section of the source wild name is matched by a missing section of the destination wild name, then that part of the actual source file name will be used as the corresponding part of the actual destination name. Otherwise the actual destination file name is taken from the destination wild name. If there are more sections in the destination wild name than in the source wild name, then these extra sections will be inserted after the drive name, and vice versa.

The full form of the command is:

WCOPY #channel, name TO name       copy files

The separator TO is used for clarity, you may use a comma instead.

If the channel is not given (i.e. most of the time), then the requests for confirmation will be sent to the command channel #0. Otherwise confirmation will be sent to the chosen channel, and the user is requested to press one of:

Y       (yes)  copy this file

N       (no)   do not copy this file

A       (all)  copy this and all the next matching files.

Q       (quit) do not copy this or any other files

If the destination file already exists, the user is requested to press one of:

Y       (yes)  copy this file, overwriting the old file

N       (no)   do not copy this file

A       (all)  overwrite the old file, and overwrite any other files requested to be copied.

Q       (quit) do not copy this or any other files

For example, if  the default data directory is flp2_, and the default destination is flp1_

WCOPY              would copy all files on flp2_ to flp1_

WCOPY flp1_,flp2_  would copy all files on flp1_ to flp2_

WCOPY fred         would copy

flp2_fred            to flp1_fred

flp2_freda_list      to flp1_freda_list

WCOPY fred,mog     would copy

flp2_fred            to flp2_mog

flp2_freda_list      to flp2_moga_list

WCOPY _fred,_mog   would copy

flp2_fred            to flp2_mog

flp2_freda_list      to flp2_moga_list

flp2_old_fred        to flp2_old_mog

flp2_old_freda_list  to flp2_old_moga_list

WCOPY _list,old__   would copy

flp2_jo_list         to flp2_old_jo_list

flp2_freda_list      to flp2_old_freda_list

WCOPY old__list,flp1__  would copy

flp2_old_jo_list     to flp1_jo_list

flp2_old_freda_list  to flp1_freda_list

5.5.3  Background Copying

A background file spooler is provided which copies files in the same way as COPY_O (Section 5.5.1), but is primarily intended for copying files to a printer. As an option, a form feed (ASCII <FF>) can be sent to the printer at the end of file.

SPL name TO name                   spool a file

SPLF name TO name                  spool a file, <FF> at end

The separator TO is used for clarity, you may use a comma instead.

The normal use of this command is with one name only:

SPL_USE ser                        set spooler default

.....

SPLF fred                          spool fred to ser, adding a form feed to the file

When used in this way, if the default device is in use, the Job will be suspended until the device is available. This means that many files can be spooled to a printer at once.

A variation on the SPL and SPLF commands is to use SuperBASIC channels in place of the filenames. These channels should be opened before the spooler is invoked:

SPL #channel3 TO #channel2

Where channel3 must have been opened for input and channel2 must have been opened for output.

5.5.4  Renaming Files

Renaming a file is a process similar to COPYing a file, but the file itself is neither moved nor duplicated, only the directory name is changed. The commands, however, are exactly the same in use as the equivalent COPY commands.

RENAME name TO name                see COPY

WREN #channel, name TO name        see WCOPY

6  SuperBASIC Programs

All the commands for loading, saving and running SuperBASIC programs have been redefined in Toolkit II. The differences are in the areas of:

a) default filenames,

b) WHEN ERROR (JS and MG ROMs only),

c) common heap handling.

6.1  DO

There is one additional procedure, DO, to execute SuperBASIC commands from file.

DO name                            do commands in file

The commands should be 'direct': any lines with line numbers will be merged into the current SuperBASIC program. The file should not contain any of the commands listed in this section (e.g. RUN, LOAD etc.), CONTINUE, RETRY or GOTO. It appears that a DO file can invoke SuperBASIC procedures without harmful effect.

A DO file can contain in line clauses:

FOR i=1 to 20: PRINT 'This is a DO file'

If you try to RUN a BASIC program from a DO file, then the file will be left open. Likewise, if you put direct commands in a file that is MERGED, then the file will be left open.

6.2  Default Directories

Most of the commands use the data default directory. In addition, the program LOADing commands will try the program default directory if a file cannot be found in the data default directory.

6.3  WHEN ERROR Problems

There is a problem in the JS and MG ROM error handling code, in that WHEN ERROR processing, once set, is never reset, even if the WHEN ERROR clause is removed by a NEW or a LOAD! All of the commands in this section clear the WHEN ERROR processing flag, and all but STOP also clear the pointer to the current WHEN ERROR clause.

6.4  Common Heap

Toolkit II contains facilities for allocating space in the common heap. This space is cleared by the commands that clear the SuperBASIC variables: LOAD, LRUN, NEW and clear.

6.5  Summary of Commands

DO name                            do commands in file

LOAD name                          load a SuperBASIC program

LRUN name                          load and run a SuperBASIC program

MERGE name                         merge a SuperBASIC program

MRUN name                          merge and run a SuperBASIC program

SAVE name, ranges                  save a SuperBASIC program

SAVE_O name, ranges                as SAVE but overwrites file if it exists

RUN line number                    start a SuperBASIC program

STOP                               stop a SuperBASIC program

NEW                                reset SuperBASIC

CLEAR                              clear SuperBASIC variables

7  Load and Save

Toolkit II provides the same binary file load and save operations as the standard QL. The differences are that the save operations will request permission to overwrite if the file already exists, and all the commands use default directories.

There are also two 'overwrite' variants for the save operations, and one new command: LRESPR.

LRESPR opens the load file and finds the length of the file, then reserves space for the file in the resident procedure area before loading the file. Finally a CALL is made to the start of the file.

The CALL procedure itself has been rewritten to avoid the problems that occur in AH and JM ROMs when a CALL is made from a large (>32 kbytes) program

LRESPR name                        load a file into resident procedure area and CALL

LBYTES name, address               load a file into memory at specified address

CALL address, parameters           CALL machine code with parameters

SBYTES name, address, size         save an area of memory

SBYTES_O name, address, size       as SBYTES but overwrites file if it exists

SEXEC name, address, size, data    save an area of memory as an executable file

SEXEC_O name, address, size, data  as SEXEC but overwrites

For SEXEC and SEXEC_O the 'data' parameter is the default data space required by the program.

If there are any Jobs in the QL (apart from Job 0 the SuperBASIC interpreter) then LRESPR will fail with the error message 'not complete'. If this happens, use RJOB to remove all the other Jobs.

8  Program Execution

There is one procedure for initiating the execution of compiled (executable) programs. This procedure is invoked by five commands: EX, EXEC (which are synonymous) EW, EXEC_W (which are synonymous) and ET. The differences are very small: when EX is complete, it returns to SuperBASIC; when EW is complete it waits until the programs initiated have finished before returning to SuperBASIC; while ET sets up the programs, but returns to SuperBASIC so that a debugger can be called to trace the execution. EX will be used to describe all the commands.

8.1  Single Program Execution

In its simplest form EX can be used to initiate a single program:

EX name

The program in the file 'name' is loaded into the transient program area of the QL and execution is initiated. If the file does not contain an executable program, a 'bad parameter' error is returned.

It is also possible to pass parameters to a program in the form of a string:

EX name; parameter string

In this case the program in the file 'name' is loaded into the transient program area, the string is pushed onto its stack and execution is initiated.

Finally it is possible for EX to open input and output files for a program as well as (or instead of) passing it parameters. If preferred, a SuperBASIC channel number may be used instead of a filename. A channel used in this way must already be open.

EX program name, file names or #channels; parameter string

Taking as an example the program UC which converts a text file to upper case, the command:

EX uc, fred, #1

will load and initiate the program UC, with fred as its input file and the output being sent to window #1.

8.2  Filters

EX is designed to set up filters for processing streams of data.

Within the QL it is possible to have a chain of cooperating jobs engaged in processing the same data in a form of production line. When using a production line of this type, each job performs a well-defined part of the total process. The first job takes the original data and does its part of the process; the partially processed data is then passed on to the next job which carries out its own part of the process; and so the data gradually passes through all the processes. The data is passed from one Job to the next through a 'pipe'. The data itself is termed a 'stream' and the Jobs processing the data are termed 'filters'.

Using the symbols   [ ] to represent a single optional item

( ) to represent a repeated optional item

the complete form of the EX command is

EX [#channel TO] prog_spec (TO prog_spec) [TO #channel]

where prog_spec is

program name (,file name or #channel) [;parameter string]

Each TO separator creates a pipe between Jobs.

All the names and the parameter string may be names, strings or string expressions. The significance of the filenames is, to some extent, program dependent; but there are two general rules which should be used by all filters:

1) the primary input of a filter is the pipe from the previous Job in the chain (if it exists), or else the first data file,

2) the primary output of a filter is the pipe to the next job in the chain (if it exists) or else the last data file.

Many filters will have only two I/O channels: the primary input and the primary output.

If the parameters of EX start with '#channel TO', then the corresponding SuperBASIC channel will be closed (if it was already open) and a new channel opened as a pipe to the first program. Any data sent to this channel (e.g. by PRINTing to it) will be processed by the chain of Jobs. When the channel is CLOSEd, the chain of Jobs will be removed from the QL.

If the parameters of EX end with 'TO #channel', then the corresponding SuperBASIC channel will be closed (if it was already open) and a new channel opened as a pipe from the last program. Any data passing through the chain of Jobs will arrive in this channel and may be read (e.g. by INPUTing from it). When all the data has passed, the Jobs will remove themselves and any further attempt to take input from this channel will get an 'end of file' error. The EOF function may be used to test for this.

8.3  Example of Filter Processing

As an example of filter processing, the programs UC to convert a file to upper case, LNO to line number a file, and PAGE to split a file onto pages with an optional heading are all chained to process a single file:

EX uc, fred TO lno TO page,ser; 'File fred at '&date$

The filter UC takes the file 'fred' and after converting it to upper case, passes through a pipe to LNO. LNO adds line numbers to each line and passes the file down a pipe to PAGE. In its turn, PAGE splits the file onto pages with the heading (including in this case the date) at the top of each page, before sending the file to the SER port. Note that the file fred itself is not modified; the modified versions are purely transient.

9  Job Control

As QDOS is a multitasking operating system, it is possible to have a number of competing or co-operating Jobs in the QL at any one time. Jobs compete for resources in line with their priority, and they may co-operate using pipes or shared memory to communicate. The basic attributes of a Job are its priority and its position within the tree of Jobs (ownership). A Job is identified by two numbers: one is the Job number which is an index into the table of Jobs, and the other is a tag which is used to identify a particular Job so that it cannot be confused with a previous Job occupying the same position in the Job table. Within QDOS the two numbers are combined into the Job ID which is Job number + tag*65536. For these Job control routines, where Job_id is a parameter of one of the Job control routines, it may be given as either a single number (the Job ID, as returned from OJob or NXJob of Toolkit II) or as a pair of numbers (Job number,Job tag). Thus the single parameter 65538 (2+1*65536) is equivalent to the two parameters 2,1.

9.1  Job Control Commands

JOBS is a command to list all the Jobs running in the QL at the time. If there are more Jobs in the machine than can be listed in the output window, the procedure will freeze the screen (CTRL F5) when it is full. The procedure may fail if Jobs are removed from the QL while the procedure is listing them. The following information is given for each Job:

the Job number

the Job tag

the Job's owner Job number

a flag 'S' if the Job is suspended

the Job priority

the Job (or program) name.

The command is

JOBS                               list current Jobs to #1

JOBS #channel                      list current Jobs

JOBS \name                         list Jobs to 'name'

There are three procedures for controlling Jobs in the QL:

RJOB id or name, error code        remove a Job

SPJOB id or name, priority         set Job priority

AJOB id or name, priority          activate a Job

If a name is given rather than a Job ID, then the procedure will search for the first Job it can find with the given name.

If there is a Job waiting for the completion of a Job removed by RJob, it will be released with D0 set to the error code.

E.g.    RJOB 3,8,-1             remove Job 3, tag 8 with error -1

SPJOB demon,1           set the priority of the Job called 'demon' to 1

9.2  Job Status Functions

The Job status functions are provided to enable a SuperBASIC program to scan the Job tree and carry out complex Job control procedures.

PJOB (id or name)                   find priority of Job

OJOB (id or name)                   find owner of Job

JOB$ (id or name)                   find Job name

NXJOB (id or name,top Job id)       find next Job in tree

NXJOB is a rather complex function. The first parameter is the id of the Job currently being examined, the second is the id of the Job at the top of the tree. If the first id passed to NXJOB is the last Job owned, directly or indirectly, by the 'top Job', then NXJOB will return the value 0, otherwise it will return the id of the next Job in the tree.

Job 0 always exists and owns directly or indirectly all other Jobs in the QL. Thus a scan starting with id = 0 and top Job id = 0 will scan all Jobs in the QL.

It is possible that, during a scan of the tree, a Job may terminate. As a precaution against this happening, the Job status functions return the following values if called with an invalid Job id:

PJOB=0    OJOB=0    JOB$=''    NXJOB=-1

10  Open and Close

All of the OPEN and CLOSE commands and functions avoid the problem that occurs using the standard QL facilities when more than 32768 files have been opened in one session.

10.1  Open Commands

The OPEN commands of the standard QL have been modified to use the data default directory. Two commands have been added to open a new file overwriting the old file if it already exists, and to open a directory.

OPEN #channel, name                open a file for read/write

OPEN_IN #channel, name             open a file for input only

OPEN_NEW #channel, name            open a new file

OPEN_OVER #channel, name           open a new file, if it exists it is overwritten

OPEN_DIR #channel, name            open a directory

10.2  File Status

The function FTEST is used to determine the status of a file or device. It opens a file for input only and immediately closes it. If the file exists it will either return the value 0 or -9 (in use error code), if it does not exist, it will return -7 (not found error code). Other possible returns are -11 (bad name), -15 (bad parameter), -3 (out of memory) or -6 (no room in the channel table).

FTEST (name)                       test status of file

The function can be used to check that a file does not exist:

IF FTEST (file$) <> -7: PRINT 'File '; file$; ' exists'

10.3  File Open Functions

This is a set of functions for opening files. These functions differ from the OPEN procedures in two ways. Firstly, if a file system error occurs (e.g. 'not found' or 'already exists') these functions return the error code and continue. Secondly the functions may be used to find a vacant hole in the channel table: if successful they return the channel number.

FOPEN (#channel, name)             open a file for read/write

FOP_IN (#channel, name)            open a file for input only

FOP_NEW (#channel, name)           open a new file

FOP_OVER (#channel, name)          open a new file, if it exists it is overwritten

FOP_DIR (#channel, name)           open a directory

When called with two parameters, these functions return the value zero for successful completion, or a negative error code.

A file may be opened for read only with an optional extension using the following code:

ferr=FOP_IN (#3,name$&'_ASM')      :REMark try to open _ASM file

IF ferr=-7: ferr=FOP_IN (#3,name$) :REMark ERR.NF, try no _ASM

The #channel parameter is optional: if it is not given, the functions will search the channel table for a vacant entry, and, if the open is successful, the channel number will be returned. Note that error codes are always negative, and channel numbers are positive.

In this example:

outch = FOP_NEW (fred)             :REMark open fred

if outch < 0: REPORT outch: STOP   :REMark ... oops

PRINT #outch, 'This is file Fred'

CLOSE #outch

there is no need to ever know the actual channel number.

10.4  CLOSE

The CLOSE command has been extended to take multiple parameters. In addition, if called with no parameters it will close all channel numbers #3 and above. It will not report an error if a channel is not open.

CLOSE #channels                    close channels

E.g. CLOSE #3, #4, #7                   close #3, #4 and #7

11  File Information

There are six functions to extract information from the header of a file.

If a file is being extended, the file length can be found by using the FPOS function to find the current file position. (If necessary the file pointer can be set to the end of file by the command GET \#n 999999.)

FLEN (#channel)                    find file length

FTYP (#channel)                    find file type

FDAT (#channel)                    find file data space

FXTRA (#channel)                   find file extra info

FNAME$ (#channel)                  find filename

FUPDT (#channel)                   find file update date

The file type is        0 for ordinary files

1 for executable programs

2 for relocatable machine code

The file information functions can also be used with implicit channels. E.g.

PRINT FLEN (#3)                    print the length of the file open on channel #3

PRINT FLEN (\fred)                 print the length of file fred

12  Direct Access Files

In QDOS, files appear as a continuous stream of bytes. On directory devices (Microdrives, hard disks etc.) the file pointer can be set to any position in a file. This provides 'direct access' to any data stored in the file. Access implies both read access and, if the file is not open for read only (OPEN_IN from SuperBASIC, IO.SHARE in QDOS), write access. Parts of a file as small as a byte may be read from, or written to any position within a file. QDOS does not impose any fixed record structures upon files: applications may provide these if they wish.

Procedures are provided for accessing single bytes, integers, floating point numbers and strings. There is also a function for finding the current file position.

To keep files tidy there is a command to truncate a file (when information at the end of a file is no longer required), and a command to flush the file buffers.

A direct access input or output (I/O) command specifies the I/O channel, a pointer to the position in the file for the I/O operation to start and a list of items to be input or output.

command #channel\position, items

It is usual (although not essential - the default is #3) to give a channel number for the direct I/O commands. If no pointer is given, the routines will read or write from the current position, otherwise the file position is set before processing the list of I/O items; if the pointer is a floating point variable rather than an expression, then, when all items have been read from or written to the file, the pointer is updated to the new current file position. If no items are given then nothing is written to or read from the file. This can be used to position a file for use by other commands (e.g. INPUT for formatted input).

12.1 Byte I/O

BGET #channel\position, items      get bytes from a file

BPUT #channel\position, items      put bytes onto a file

BGET gets 0 or more bytes from the channel. BPUT puts 0 or more bytes into the channel. For BGET, each item must be a floating point or integer variable; for each variable, a byte is fetched from the channel. For BPUT, each item must evaluate to an integer between 0 and 255; for each item a byte is sent to the output channel.

For example the statements

abcd=2.6

zz%=243

BPUT #3,abcd+1,'12',zz%

will put the byte values 4, 12 and 243 after the current file position on the file open on #3.

Provided no attempt is made to set a file position, the direct I/O routines can be used to send unformatted data to devices which are not part of the file system. If, for example, a channel is opened to an Epson compatible printer (channel #3) then the printer may be put into condensed underline mode by either

BPUT #3,15,27,45,1

or PRINT #3,chr$(15);chr$(27);'-';chr$(1);

Which is easier?

12.2 Unformatted I/O

It is possible to put or get values in their internal form. The PRINT and INPUT commands of SuperBASIC handle formatted IO, whereas the direct I/O routines GET and PUT handle unformatted I/O. For example, if the value 1.5 is PRINTed the byte values 49 ('1'), 46 ('.') and 53 ('5') are sent to the output channel. Internally, however, the number 1.5 is represented by 6 bytes (as are all other floating point numbers). These six bytes have the value 08 01 60 00 00 00 (in hexadecimal). If the value is PUT, these 6 bytes are sent to the output channel.

The internal form of an integer is 2 bytes (most significant byte first). The internal form of a floating point number is a 2 byte exponent to base 2 (offset by hex 81F), followed by a 4 byte mantissa, normalised so that the most significant bits (bits 31 and 30) are different. The internal form of a string is a 2 byte positive integer, holding the number of characters in the string, followed by the characters.

GET #channel\position, items       get internal format data from a file

PUT #channel\position, items       put internal format data onto a file

GET gets data in internal format from the channel. PUT puts data in internal format into the channel. For GET, each item must be an integer, floating point, or string variable. Each item should match the type of the next data item from the channel. For PUT, the type of data put into the channel, is the type of the item in the parameter list. The commands

fpoint=54

...

wally%=42: salary=78000: name$='Smith'

PUT #3\fpoint, wally%, salary, name$

will position the file, open on #3, to the 54th byte, and put 2 bytes (integer 42), 6 bytes (floating point 78000), 2 bytes (integer 5) and the 5 characters 'Smith'. Fpoint will be set to 69 (54+2+6+2+5).

For variables or array elements the type is self evident, while for expressions there are some tricks which can be used to force the type:

.... +0         will force floating point type;

.... &''        will force string type;

.... ||0        will force integer type.

xyz$='ab258.z'

...

PUT #3\37,xyz$(3 to 5)||0

will position the file opened on channel #3 to the 37th byte and then will put the integer 258 on the file in the form of 2 bytes (value 1 and 2, i.e. 1*256+2).

12.3  Truncate File

TRUNCATE #channel\position         truncate file

If the position is not given, the file will be truncated to the current position

TRUNCATE #dbchan                   truncate the file open on channel dbchan

12.4  Flush Buffers

FLUSH #channel                     flush file buffers

QDOS directory device drivers maintain as much of a file in RAM as possible. A power failure or other accident could result in a file being left in an incomplete state. The FLUSH procedure will ensure that a file is updated without closing it. Closing a file will always cause the file to be flushed. Toolkit II includes an upgrade to the microdrive routines to perform a complete flush. FLUSH will not work with Micro Peripherals disk systems.

12.5  File Position

There is one function to assist in direct access I/O: FPOS returns the current file position for a channel. The syntax is:

FPOS (#channel)                    find file position

For example:

PUT #4\102,value1,value2

ptr = FPOS (#4)

will set 'ptr' to 114 (=102+6+6).

The file pointer can be set by the commands BGET, BPUT, GET or PUT with no items to be got or put. If an attempt is made to put the file pointer beyond the end of file, the file pointer will be set to the end of file and no error will be returned. Note that setting the file pointer does not mean that the required part of the file is actually in a buffer, but that the required part of the file is being fetched. In this way, it is possible for an application to control prefetch of parts of a file where the device driver is capable of prefetching.

13  Format Conversions

Toolkit II provides a number of facilities for fixed format I/O. These include binary and hexadecimal conversions as well as fixed format decimal. Most of these are in the form of functions but one new command is included.

13.1 PRINT_USING

PRINT_USING is a fixed format version of the PRINT command:

PRINT_USING #channel, format, list of items to print

The 'format' is a string or string expression containing a template or 'image' of the required output. Within the format string the characters +-#*,.!\'"$ and  all have special meaning. When called, the procedure scans the format string, writing out the characters of the string, until a special character is found.

If the  character is found, then the next character is written out, even if it is a special character.

If the character is a " or ', then all the following characters are written out until the next " or '.

If the \ character is found, then a newline is written out.

All the other special characters appear in format 'fields'. For each field an item is taken from the list, and formatted according to the form of the field and written out.

The field determines not only the format of the item, but also the width of the item (equal to the width of the field). The field widths in the examples below are arbitrary.

field              format

#####          if item is string, write string left

justified or truncated

otherwise write integer right justified

*****          write integer right justified empty part

of field filled with * (e.g. ***12)

####.##        fixed point decimal (e.g.   12.67)

****.**        fixed point decimal, * filled (e.g. **12.67)

##,###.##      fixed point decimal, thousands separated

**,***.**        by commas (e.g  1,234.56 or *1,234.56)

-#.####!!!!    exponent form (e.g. 2.9979E+08) optional sign

+#.####!!!!    exponent form always includes sign

The exponent field must start with a sign, one #, and a decimal point (comma or full stop). It must end with four !s.

Any decimal field may be prefixed or postfixed with a + or -, or enclosed in parentheses. If a field is enclosed in parentheses, then negative values will be written out enclosed in parentheses. If a - is used then the sign is only written out if the value is negative; if a + is used, then the sign is always written out. If the sign is at the end of the field, then the sign will follow the value.

Numbers can be written out with either a comma or a full stop as the decimal point. If the field includes only one comma or full stop, then that is the character used as the decimal point. If there is more than one in the field, the last decimal point found (comma or full stop) will be used as the decimal point, the other is used as the thousands separator. Long live European unity!

If the decimal point comes at the end of the field, then it will not be printed. This allows currencies to be printed with the thousands separated, but with no decimal point (e.g 1,234).

Floating currency symbols are inserted into fields using the $ character. The currency symbols are inserted between the $ and the first # in the field (e.g. $Dm#.###,## or +$$##,###.##). When the value is converted, the currency symbols are 'floated' to the right to meet the value.

For example

fmt$='$ Charges *******.** : ($SKr##.###,##) : ##,###.##+\'

PRINT_USING fmt$, 123.45, 123.45, 123.45

PRINT_USING fmt$, -12345.67, -12345.67, -12345.67

PRINT_USING '-#.###!!!!\', 1234567

will print

$ Charges ****123.45 :     SKr123,45  :    123.45+

$ Charges *-12345.67 : (SKr12.345,67) : 12,345.67-

1.235E+06

13.2  Decimal Conversions

These routines convert a value into a decimal number in a string. The number of decimal places represented is fixed, and the exponent form of floating point number is not used.

FDEC$ (value, field, ndp)          fixed format decimal

IDEC$ (value, field, ndp)          scaled fixed format

CDEC$ (value, field, ndp)           decimal

The 'field' is length of the string returned, 'ndp' is the number of decimal places.

The three routines are very similar. FDEC$ converts the value as it is, whereas IDEC$ assumes that the value given is an integral representation in units of the least significant digit displayed. CDEC$ is the currency conversion which is similar to IDEC$, except that there are commas every 3 digits.

FDEC$ (1234.56,9,2)      returns '  1234.56'

IDEC$ (123456,9,2)       returns '  1234.56'

CDEC$ (123456,9,2)       returns ' 1,234.56'

If the number of characters is not large enough to hold the value, the string is filled with '*'. The value should be between -2^31 and 2^31 (-2,000,000,000 to +2,000,000,000) for IDEC$ and CDEC$, whereas for FDEC$ the value multiplied by 10^ndp should be in this range.

13.3  Exponent Conversion

There is one function to convert a value to a string representing the value in exponent form.

FEXP$ (value, field, ndp)          fixed exponent format

The form has an optional sign and one digit before the decimal point, and 'ndp' digits after the decimal point. The exponent is in the form of 'E' followed by a sign followed by 2 digits. The field must be at least 7 greater than ndp. E.g.

FEXP$ (1234.56,12,4)        returns '  1.2346E+03'

13.4 Binary and Hexadecimal

HEX$ (value, number of bits)       convert to hexadecimal

BIN$ (value, number of bits)       convert to binary

These return a string of sufficient length to represent the value of the specified number of bits of the least significant end of the value. In the case of HEX$ the number of bits is rounded up to the nearest multiple of 4.

HEX (hexadecimal string)           hexadecimal to value

BIN (binary string)                binary to value

These convert the string supplied to a value. For BIN, any character in the string, whose ASCII value is even, is treated as 0, while any character, whose ASCII value is odd, is treated as 1. E.g. BIN ('.#.#') returns the value 5. For HEX the 'digits' '0' to '9' 'A' to 'F' and 'a' to 'f' have their conventional meanings. HEX will return an error if it encounters a non-recognised character.

14  Display Control

There are three separate facilities provided to extend the display control operations of the QL. They are cursor control, character fount control and window reset.

14.1  Cursor Control

The function INKEY$ is designed so that keystrokes may be read from the keyboard without enabling the cursor. Two procedures are supplied to enable and disable the cursor. When the cursor is enabled, it will usually appear solid (inactive). The cursor will start to flash (active) when the keyboard queue has been switched to the window with the cursor (e.g. by an INKEY$).

CURSEN #channel                    enable the cursor

CURDIS #channel                    disable the cursor

Note that while CURSEN and CURDIS default to channel #1, like most IO commands, INKEY$ defaults to channel #0.

For example:

CURSEN: in$=INKEY$ (#1,250): CURDIS

will enable the cursor in window #1, and wait for up to 5 seconds for a character from the keyboard. If nothing is typed within the 5 seconds, then in$ will be set to a null string ("").

14.2  Character Fount Control

The QL display driver has two character founts built in. The first provides patterns for the values 32 (space) to 127 (copyright), while the second provides patterns for the values 127 (undefined) to 191 (down arrow). For each character the display driver will use the appropriate pattern from the first fount, if there is one, failing that, it will use the appropriate pattern from the second fount, failing that, it will use the first defined pattern in the second fount.

Substitute founts need not have the same range of values as the built in founts. A fount could, for example, be defined to have all values from 128 to 255.

The format of a QL fount is:

byte               lowest character value in the fount

byte               number of valid characters-1

9 bytes of pixels for the lowest character value

9 bytes of pixels for the next character value, etc.

The pixels are stored with the top line in the lowest address byte. For each pixel a bit set to one indicates INK, a bit set to zero indicates paper. The leftmost pixel is in bit 6 of the byte.

The character 'g' is stored as:         %00000000

%00000000

%00111000

%01000100

%01000100

%01000100

%00111100

%00000100

%00111000

The command CHAR_USE is used to set or reset one or both character founts.

CHAR_USE #channel, addr1, addr2    addr1 and addr2 both point to substitute founts

CHAR_USE #channel, 0, addr2        the built in first fount will be used, addr2 points to a substitute second fount

CHAR_USE 0,0                       reset both founts for window #1

The QL display driver assumes that all characters are 5 pixels wide by 9 pixels high. Other sizes are obtained by doubling the pixels or by adding blank pixels between characters. It is possible, with Toolkit II, to set any horizontal and vertical spacing. If the increment is set to less than the current character size (set by CSIZE) then extreme caution is required as it will be possible for the display driver to write characters (at the right hand side or bottom of the window) partly outside the window. The windows should not come closer to the bottom or right hand edges of the screen than the amount by which the increment specified is smaller than the character spacing set by CSIZE.

CHAR_INC #channel, x inc, y inc    set the character x and y increments

The channel is defaulted to #1.

The character increments specified are cancelled by a CSIZE command.

For example, if there is a 3x6 character fount in a file called 'f3x6' (length 875 bytes), then a 127 column by 36 row screen can be set up:

MODE 4

WINDOW 512-2,256-3,0,0     :REMark clear of edges of screen

CSIZE 0,0                  :REMark spacing 6x10

CHAR_INC 4,7               :REMark spacing 4x7

:

fount = ALCHP (875)        :REMark reserve space for fount

LBYTES f3x6, fount         :REMark load fount

CHAR_USE fount,0           :REMark single fount only

14.3  Resetting the Windows

There are two commands for resetting the windows to the turn-on state:

WMON mode                          reset to 'Monitor'

WTV mode                           reset to 'TV' windows

The mode should be 0, 4 or 512 for the 4 colour (512 pixel) mode, or 8 or 256 for the 8 colour (256 pixel) mode. Only the window sizes, positions and borders are reset by these commands, the paper strip and ink colours remain unchanged.

15  Memory Management

As QDOS is a multitasking operating system, there may be several jobs running in a QL, and so the amount of free memory may vary unpredictably. No Job may assume that the amount of free memory is fixed. The function FREE_MEM may be used to guess at the free memory (defined as the space available for filing system slave blocks less the space required for two (c.f. QL Toolkit: one only) slave blocks.

Temporary space may be allocated in the 'common heap'. This is done with the function ALCHP which returns the base address of the space allocated. Individual allocations may be returned to QDOS with the command RECHP, or all space allocated is released by the commands CLCHP (clear common heap), CLEAR or NEW.

Functions:

FREE_MEM                           find the amount of free memory

ALCHP (number of bytes)            allocates space in common heap (returns the base address of the space)

Commands:

RECHP base address                 return space to common heap

CLCHP                              clear out all allocations in the common heap

Making large allocations in the common heap and then accessing a drive for the first time, can cause a terrible heap disease called 'large scale fragmentation' where the drive definition blocks become widely scattered in the heap leaving large holes that cease to be available except as heap entries (i.e. you cannot load programs into them). A simple but dangerous cure is to delete the drive definition blocks.

DEL_DEFB                           delete file definition blocks from common heap

Although there are precautions within the procedure DEL_DEFB to minimise damage, care should be taken to avoid using this command while any directory device is active.

16  Procedure Parameters

In QL SuperBASIC procedure parameters are handled by substitution: on calling a procedure (or function), the dummy parameters in the procedure definition become the actual parameters in the procedure call. The type and usage of procedure parameters may be found with two functions:

PARTYP (name)                      find type of parameter

PARUSE (name)                      find usage of parameter

the type is  0 null            the usage is  0 unset

1 string                        1 variable

2 floating point                2 array

3 integer

One of the 'tricks' used by many machine code procedures is to use the 'name' of an actual parameter rather than the 'value' (e.g. 'LOAD fred' to load the file name fred). Given the name of a dummy parameter of a procedure, it would be possible to find the name of an actual parameter of a SuperBASIC procedure call, but it would be very slow. It is much easier to find the name of an actual parameter, if the position in the parameter list is known.

PARNAM$ (parameter number)         find name of parameter

For example the program fragment

pname fred, joe, 'mary'

....

DEF PROC pname (n1,n2,n3)

PRINT PARNAM$(1), PARNAM$(2), PARNAM$(3)

END DEF pname

would print 'fred    joe      ' (the expression has no name).

One further 'trick' is to use the value of the actual argument if it is a string, otherwise use the name. This is possible in SuperBASIC procedures using the slightly untidy PARSTR$ function.

PARSTR$ (name, parameter number)   if parameter 'name' is a string, find the value, else find the name.

For example the program fragment

pstring fred, joe, 'mary'

....

DEF PROC pstring (n1,n2,n3)

PRINT PARSTR$(n1,1), PARSTR$(n2,2), PARSTR$(n3,3)

END DEF pstring

would print 'fred    joe     mary'.

17  Error Handling

The JS and MG QL ROMs contain unfinished code for error trapping in SuperBASIC: Toolkit II corrects some of the remaining problems.

Error handling is invoked by a WHEN ERROR clause. Unlike procedure and function definitions, these clauses are static. The error handling within a WHEN ERROR clause is set up when the clause is executed, but is only actioned WHEN an ERROR occurs. This means that a program may have more than one WHEN ERROR clause. As each one is executed, the error processing within that clause replaces the previously defined error processing.

The clause is opened with a WHEN ERROR statement, and closed with an END WHEN statement. Within the clause there may be any normal type of statement. (Although it might be better to avoid calling SuperBASIC functions or procedures!) A WHEN ERROR clause is exited by a STOP, CONTINUE, RETRY, RUN, LOAD or LRUN command (if you are using Toolkit II). Furthermore the Toolkit II versions of RUN, NEW, CLEAR, LOAD, LRUN, MERGE and MRUN reset the error processing (an unfortunate omission from the QL ROMs).

There are some additional facilities intended for use within WHEN ERROR clauses.

ERROR functions

These functions correspond to each of the system error codes

(ERR_NC, ERR_NJ, ERR_OM, ERR_OR, ERR_BO, ERR_NO, ERR_NF, ERR_EX, ERR_IU, ERR_EF, ERR_DF, ERR_BN, ERR_TE, ERR_FF, ERR_BP, ERR_FE, ERR_XP, ERR_OV, ERR_NI, ERR_RO, ERR_BL) and return the value TRUE if the error, which caused the WHEN ERROR clause to be invoked, is of that type. Do NOT use ERR_DF without Toolkit II.

ERROR information

ERLIN                              returns the line number where the error occurred

ERNUM                              returns the error number

ERROR reporting

REPORT #channel                    reports the last error

REPORT                             reports the last error to channel #0

REPORT #channel, error number      reports the error number given

RETRY and CONTINUE

As the RETRY and CONTINUE exit from an error clause without resetting the WHEN ERROR, it would be useful if they could also be used to exit to a different part of the program. In Toolkit II, RETRY and CONTINUE can have a line number.

CONTINUE line number               continue or retry from a

RETRY line number                    specified line

18  Timekeeping

18.1  Resident Digital Clock

CLOCK                      default clock in its own window

CLOCK #channel             default clock, 2 rows of 10 chars

CLOCK #channel, string     user defined clock

CLOCK is a procedure to set up a resident digital clock using the QL's system clock. If no window is specified, then a default window is set up in the top RHS of the monitor mode default channel 0. This window is 60 by 20 pixels and is only suitable for four colour mode. The clock may be invoked to execute within a window set up by BASIC. In this case the clock job will be removed when the window is closed.

The string is used to define the characters written to the clock window: any character may be written except $ or %. If a dollar sign is found in the string then the next character is checked and

$d or $D will insert the three characters of the day of week,

$m or $M will insert the three characters of the month.

If a percentage sign is found then

%y or %Y will insert the two digit year

%d or %D will insert the two digit day of month

%h or %H will insert the two digit hour

%m or %M will insert the two digit minute

%s or %S will insert the two digit second

The default string is '$d %d $m  %h/%m/%s ' a newline should be forced by padding out a line with spaces until the right hand margin of the window is reached.

To set the clock the SuperBASIC command SDATE is used:

SDATE year,month,day,hour,minute,seconds

Example:

SDATE 1989,6,1,14,45,30

MODE 8

OPEN #6,'scr_156x10a32x16'

INK #6,0: PAPER #6,4

CLOCK #6,'QL time %h:%m'

18.2  Alarm Clock

ALARM time             set alarm clock to sound at given time

The time should be specified as two numbers: hours (24 hour clock) and minutes:

ALARM 14,30                alarm will sound at half past two

19  Extras

EXTRAS #channel                    lists the extra facilities linked into SuperBASIC

EXTRAS                             lists the extras to #1

If the output channel is a window, the screen is frozen (CTRL F5) when the window is full. With Toolkit II installed, there are hundreds of extras.

TK2_EXT                            enforces the Toolkit II definitions of common commands and functions

If, for any reason, some of the Toolkit II extensions have been re-defined, TK2_EXT (c.f. FLP_EXT floppy disk extensions, EXP_EXT expansion unit extensions) will reassert the Toolkit II definitions.

20  Console Driver

20.1  Keyboard Extensions

There are two extensions to the QL keyboard handling. The first provides a last line recall facility, and the second assigns a string of characters to an 'ALT' keystroke.

<ALT><ENTER>                       keystroke recovers the last line typed

This keystroke recovers (on a per-window basis) the last line typed, provided only that the keyboard buffer is long enough to hold it.

The ALTKEY command assigns a string to an 'ALT' keystroke (hold the ALT key down and press another key). The string itself may contain newline characters, or, if more than one string is given, then there will be an implicit newline between the strings. Thus a null string may be put at the end to add a newline to the string.

ALTKEY character, strings          assign a string to <ALT> character keystroke

For example after the command

ALTKEY 'r', 'RJOB "SPL"',''

or ALTKEY 'r', 'RJOB "SPL"' & CHR$(10)

when ALT r is pressed, the command 'RJOB "SPL"' will be executed.

ALTKEY 'r'      will cancel the ALTKEY string for 'r', while

ALTKEY          will cancel all ALTKEY strings

21  Microdrive Driver

21.1  Microdrive extensions

There are three extensions to the microdrive filing system. These are available as operating system entry  points, but may also be supported as calls from SuperBASIC.

OPEN OVERWRITE  Trap #2, D0=1, D3=3

This variant of the OPEN call opens a file for write/read whether it exists or not. The file is truncated to zero length before use.

RENAME          Trap #3, D0=4A, A1 points to new name

This call renames a file. The name should include the drive name (e.g. FLP1_NEW_NAME).

TRUNCATE        Trap #3, D0=4B

This call truncates a file to the current byte position.

21.2  Microdrive Improvements

The FS.FLUSH filing system call has been extended to perform a complete flush including  header information. This operation may be accessed through the FLUSH command.

22  Network Driver

Attempts have been made in Toolkit II to elevate the rather elementary network facilities of the QL to a useful level. The network performance is dominated by the exceptionally low capability of the network hardware. (If your QL has a pre-D14 serial number then it is highly possible that your network hardware does not work at all, although recent experience has shown that many more pre-D14 QLs have a working network port than is generally supposed.)

22.1  Network Improvements

Each QL connected to a network should have a unique 'station number' in the range 1 to 63. This is set using the NET command.

NET station number

Toolkit II provides a new protocol for broadcast which includes new provisions for handshaking. A broadcast is a message sent from one QL to all other QLs listening to the network. The Toolkit II broadcast protocol has a positive NACK (not acknowledged) handshake as well as provision for detecting BREAK. The device names for the network are:

NETO_station number                output to station number

NETO_0                             send broadcast

NETI_station number                input from station number

NETI_my station nunber             input from any station

NETI_0                             receive a broadcast

NETI_0_buffer size                 receive a broadcast into specified buffer size

When opening a channel to receive a broadcast, a buffer is opened to allow the entire transmission to be received uninterrupted. If no buffer size is specified, then all but 2k bytes of the free memory will be taken. The buffer size should be specified in kbytes. For example:

NETI_0_10                          receive a broadcast into 10 kbyte buffer

When a network output channel is closed, then (as with the QL network driver) the network driver will keep trying to send the last buffer for approximately 20 seconds in case the receiving station is busy with its Microdrives. With Toolkit II, however, after about 5 seconds the driver will start checking for a BREAK.

22.2  File Servers

The file server provided in Toolkit II is a program which allows IO resources attached to one QL to be accessed from another QL. This means that, for example, disk drives attached to just one QL can be accessed from several different QLs. The file server only needs to be running on the QL with the shared IO resource. This version of the file server is more general than the first version in that the IO resources may be pure serial devices (such as modems or printers) or windows on the QL display as well as file system devices (such as disk drives).

FSERVE                             invokes the 'file server'

There may be more than one QL on a network with a file server running: the station numbers for these QLs should be as low as possible, and should not be greater than 8.

It is possible that files opened across the network may be left open. This can occur if a remote QL is removed from the network, is turned off or is reset. To correct this condition, wait until all other remote QLs have finished their operations on this QL, then remove the file server and restart with the commands

RJOB SERVER

FSERVE

22.3  Accessing the File Server

The network file servers are accessed from remote QLs using a compound device name:

Nstation number_IO device          the name of a remote IO device (e.g. N2_FLP1_ is floppy 1 on network station 2)

For example

LOAD n2_flp1_fred                  loads file 'fred' from floppy 1 on network station 2

OPEN_IN #3,n1_flp2_myfile          opens 'myfile' on floppy 2 on network station 1

OPEN #3,n1_con_120x20a0x0          opens a 20 column 2 row window on net station 2

The use of directory default names makes this rather simpler. For example

PROG_USE n1_win1_progs             by default all programs will be loaded from directory 'progs' on Winchester disk 1 on network station 1

SPL_USE n1_ser                     set the default spooler destination to SER1 on network station 1

It is possible to hide the network from applications by setting a special name for a network file server.

NFS_USE name, network names        sets the network file server name

The 'network names' should be complete directory names, and up to eight network names may be given in the command. Each one of these network names is associated with one of the eight possible directory devices ('name'1 to 'name'8).

For example

NFS_USE mdv,n2_flp1_,n2_flp2_      sets the network file server name so that any reference to 'mdv1' on this remote QL, will be taken to be a reference flp1 on net station 2, likewise 'mdv2' will be taken to be flp2 on net station 2

OPEN_NEW #3,mdv2_fred              now this will open file 'fred' on floppy 2 on network station 2

The network names will normally just be a network number followed by a device name as above and will end with an underscore to indicate that the name is a directory. Indeed if the network file server name is to be used with the wild card file maintenance commands, this is the only acceptable form. QUILL, however, tends to open a file with the name DEF_TMP on mdv2_. Clearly, there will be problems if more than one copy of QUILL is run across the network at any one time. This can be avoided if the network name for mdv2_ is set to be a directory:

NFS_USE mdv,n1_flp1_,n1_flp2_fred_ DEF_TMP opened on mdv2_ will now appear in directory 'fred' on flp2_ on network station 1

FLP_USE FLP is invoked after reset so if FLP is to be used  as the device name in the NFS_USE command remember to include FLP_USE XXX. This will stop the TRUMP CARD / GOLD CARD etc. from trying to access its own disk port instead of the network.

FLP_USE xyz                         set device name for floppies to xyz

NFS_USE flp,n1_flp1_,n1_flp2_       any reference to 'flp1' on this QL will access flp1 on net station 1, etc.

22.4 Messaging

The Toolkit II network facilities may also be used for messaging. A window may be opened, a message sent, and a reply read using a simple SuperBASIC program. If particularly pretty messages are required, then the graphics facilities of SuperBASIC may also be used. The only standard IO facilities not available across the network are SD.EXTOP (extended operations) and SD.FOUNT (setting the founts).

For example

ch = FOPEN (n2_con_150x10a0x0): CLS #ch

INPUT #ch,'Do you want coffee? ';rep$

IF 'y' INSTR rep$ = 1 : PRINT 'Fred wants coffee'

CLS #ch: CLOSE #ch

23  Writing programs to use with EX

Programs invoked by EX (or EW or ET) fall into three classifications:

non standard            program header is not standard format;

special                 program header is standard but there is an additional flag;

standard                program header is standard.

So far as EX is concerned, the distinction is that a special program must contain the code to open its own I/O channels.

At the start of execution a standard or non-standard program will have the following information on the stack:

word    the total number of channels open for this Job

[long    the channel ID of the input pipe, if present]

(long    the channel ID of each filename given in prog_spec)

[long    the channel ID of the output pipe, if present]

word    the length of the option string or 0

[bytes   the bytes of the option string]

If there is just one channel open for a Job, then it is opened for read/write unless it is a pipe in which case the direction is implied in the command.

If there is more than one channel open for a Job, then the first channel is the primary input (opened for read only), and the others are opened OVERWRITE. The last channel is the primary output.

A Job should not close the channels supplied, but, when complete, it should commit suicide. Each Job is owned by the next one in the chain, so that when the last job has completed, the entire chain is removed. Committing suicide in this way will put an end of file in the output. Thus an end of file from the primary input should, directly or otherwise, indicate to a program that the data is complete.

23.1 Special Programs

Standard and special programs have the value $4AFB in bytes 6 and 7. This is followed by a standard string (length in a word followed by the bytes of the program identification). In the case of a special program header a further value of $4AFB (aligned on a word boundary) follows the identification. When the program has been loaded, the option string put on the jobs stack and the input pipe (if it is required) opened and its ID put on the job's stack, then EX will make a call to the address after the second identifying word. Note that the code called will form part of a BASIC procedure, not part of an executable program.

On entry to this code, the following registers will be set:

D4.L    0 or 1 if there is an input pipe; ID is not on stack

D5.L    0 or 1 if there is an output pipe; ID is on stack

D6.L    Job ID for this program

D7.L    total number of pipes + file names in prog_spec

A0      address of support routines

A1      pointer to command string

A3,A6  *pointer to first file name (name table)

A4      pointer to job's stack

A5,A6  *pointer beyond last file name (name table)

*these are the standard BASIC procedure parameter passing registers.

The file setup procedure should decode the file names, open the files required and put the IDs on the stack (A4). Register D0 should be set to the error code on return. D5 must be incremented by the number of channel IDs put on the job's stack. A4 must be maintained as the job's stack pointer. Registers D1 to D7, A0 to A3 and A5 may be treated as volatile.

The routine (A0) to get a file name should be called with the pointer to the appropriate name table entry in A3. D0 is returned as the error code, D1 to D3 are smashed. If D0 is 0, A1 is returned as the pointer to the name (relative to A6). If D0 is positive, A0 is returned as the channel ID of the SuperBASIC channel (if the parameter was #n), all other address registers are preserved.

The routine 2(A0) to open a channel should be called with the pointer to the file name in A1 (relative to A6). The file name should not be in the BASIC buffer; D3 should hold the access code (overwrite is supported) and the job ID (as passed to the initialisation routine) should be in D6. The error code is returned in D0, while D1 and D2 are smashed, and A1 is returned pointing to the file name used (it may have a default directory in front). If the open fails, A1 will point to the default+given filename. The channel ID is returned in A0 and all other registers are preserved.

In both cases the status register is returned set according to the value of D0.

Appendix A

The appendix illustrates the use of Toolkit II facilities with the GST assembler and linker. (The version used by QJUMP is supplied by GST with their QC compiler: QC is well worth buying just to get the assembler and linker!). The programs accept a wide variety of options on their command line. This command line can be passed to the programs in the parameter string of the EX command. Unfortunately the programs do not attempt to find the default data directory, so it is necessary to add this to the file names in the command line. The assembler is called ASM and the linker LINK. Filenames can be passed to these procedures as strings or names.

100 REMark assemble a relocatable file

110 :

120 DEFine PROCedure asr (file$)

130   EX asm; DATAD$ & PARSTR$ (file$,1) &  ' -errors scr'

140 END DEFine asr

150 :

160 REMark assemble with listing

170 :

180 DEFine PROCedure asl (file$)

190   EW asm; DATAD$ & PARSTR$ (file$,1) & ' -list ser -nosym'

200 END DEFine asl

210 :

220 REMark link program

230 :

240 DEFine PROCedure lk (file$)

250   EX link;DATAD$&PARSTR$(file$,1)&' -with '&DATAD$&'link -nolis

260 END DEFine lk

If the data default directory is 'FLP1_JUNK_', then the procedure calls

ASR 'table' and  LK master

will create the command parameter strings to the assembler and linker

'FLP1_JUNK_table -list ser -nosym'     and

'FLP1_JUNK_master -with FLP1_JUNK_link -nolist'

Appendix B: QL Network Protocols

Standard QL Handshake

The Standard QL handshaking network protocol is compatible with the Sinclair Spectrum protocol. It comprises 11 phases

sender                  receiver

a) scout

1) gap     waiting for 3ms for

activity, if activity

occurs: restart

2) wait                            waiting for activity

(a scout)

3) scout   send a scout of         wait for 530us

duration < 530us, if

contention occurs:

restart

b) header

4) hactiv  set net active 22us     wait for active

5) hbytes  for each byte 11.2us    for each byte wait for

start (inactive) bit,   start (inactive) bit,

8*11.2us data bits,     read 8 data bits, if

5*11.2us stop (active)  fails: restart

bits

6) hackw   wait for 2.5ms for      set net active 22us

active, if not active:

restart

7) hackbt  wait for start bit,     send 11.2us start bit

read 8 data bits,       8 data bits 00000001

if error: restart

c) data

8) dactiv  set net active 22us     wait for active

9) dbytes  for each byte 11.2us    for each byte wait for

start (inactive) bit,   start (inactive) bit,

8*11.2us data bits,     read 8 data bits, if

5*11.2us stop (active)  fails: restart

bits

10) dackw   wait for 2.5ms for      set net active 22us

active, if not active:

restart

11) dackbt  wait for start bit,     send 11.2us start bit

read 8 data bits,       8 data bits 00000001

if error: restart

The entire protocol is synchronised by a period of inactivity at least 2.8ms long.

The header is eight bytes long in the following format:

destination station number

sending station number

block number (high byte)

block number (low byte)

block type (0 normal, 1=last block of file)

number of bytes in block (0 to 255)

data checksum

header checksum

If the number of bytes in a block is 0, 256 data bytes are actually sent.

The checksums are formed by simple addition: if there are two single bit errors in the most significant bit (the most common type of error) within one block, then the errors will pass undetected. If the block number received in a header is not equal to the block number required, then the header and data block are acknowledged but ignored.

The protocol is not proof against a failure on the last block transmitted where the receiver has accepted the block, but the sender has missed the acknowledge. In this case the sender will keep re-transmitting the block until it times out (about 20s).

Toolkit II Broadcast

Toolkit II has a special version of this protocol for network broadcast. This has an extended scout to allow time for the receiver to interrogate the IPC without missing the scout, and it has an active acknowledge / not acknowledge. The protocol has been defined in such a way that future network drivers can be more flexible than the Toolkit II driver.

sender                  receiver

a) scout

1) gap     waiting for 3ms for

activity, if activity

occurs: restart

2) wait                            waiting for activity

(a scout) every 20ms

check IPC for BREAK

3) scout   send a scout of         wait for 530us

duration < 530us, if

contention occurs:

restart

4) scext   send a scout extension

of 5ms active

b) header

5) hbytes  for each byte 11.2us    for each byte wait for

start (inactive) bit,   start (inactive) bit,

8*11.2us data bits,     read 8 data bits, if

5*11.2us stop (active)  fails: nack

bits

6) hwait   leaving net active,

wait 1ms

c) data

7) dbytes  for each byte 11.2us    for each byte wait for

start (inactive) bit,   start (inactive) bit,

8*11.2us data bits,     read 8 data bits if

5*11.2us stop (active)  fails: nack

bits

8) dack    inactivate net and      within 500us set net

wait 1ms for active:    active and wait 5ms,

if fails, restart       do any processing

required and when ready

for next packet,

inactivate and restart

d) Not acknowledge

9) nack    wait for inactive       wait for 2.8us of active

or inactive, if inactive:

restart

10) nackw   wait 500us for active:  wait 200us for active, if

timeout is ok, active   active: restart, if inactive

is fail                 activate 500us (nack)

A broadcast acknowledge is 5ms active followed by more than 400us inactive. A broadcast not acknowledge is no response or 5ms active followed by 200us to 300us inactive, followed by more than 200us active.

Toolkit II Server Protocol

The Toolkit II server protocol is physically the same as the Standard QL protocol, but the header has been slightly changed to improve the checksum, to allow blocks of up to 1000 bytes to be sent and to distinguish server transactions. A server header cannot be confused with a standard header.

Appendix C: Toolkit II Code Sizes

Component

Size

Nr

Size/Nr

Base area and tables

1618

1

1618

ED

2328

1

2328

VIEW

74

1

74

Directory control (DATA_USE, DLIST etc.)

224

11

20

File maintenance (COPY, WDEL etc)

1356

13

104

SPL, SPLF

212

2

106

BASIC (LOAD, SAVE, RUN etc.)

308

13

24

Load and save (LBYTES, SBYTES, etc.)

182

6

30

CALL

30

1

30

EX, EW

750

2(3?)

375

JOB control procedures

292

4

73

JOB information functions

102

4

25

OPEN and FOPEN

122

11

11

CLOSE

60

1

60

File header information

86

6

14

Direct access files

518

7

74

PRINT_USING

442

1

442

Decimal conversions (required for PRINT_USING)

552

4

138

Hex and binary conversions

214

4

53

Cursor control

24

2

12

Character setting (CHAR_USE, CHAR_INC)

56

2

28

Window reset (includes 48 bytes in header)

128

2

64

Heap handling

146

4

38

Heap tidy (DEL_DEFB)

62

1

62

BASIC procedure parameter type

136

4

34

ERROR handling

54

2

27

EXTRAS

68

1

68

Microdrive extensions

720

4

180

ALTKEY and last line recall

366

2

183

Network

3064

3

1021

Utility code

1674

The sizes above do not include the table entries for each BASIC extension (=name length + 3 or 4 bytes).

Facilities not included in above:

RAM disk approx 1400.

Buffered printer extension approx 500.

Total approx 2400.

These can be accommodated by removing about 50 of the less useful facilities.

Appendix D: Toolkit II Update Record

V2.01  First full version.

V2.02  First release version.

V2.03  Patched to prevent MG initialisation problems.

V2.04  (Jeaggi only) network eof problems fixed.

V2.05  Lost channel on OPEN_NEW (file already exists) fixed. EX EW changed so that owner is current job.

V2.06  EX EW changed for compiled programs: EX jobs owned by 0, EW jobs owned by current job and now wait!

V2.07  (Sandy only) 'bad line' character wrap problem in ED fixed.

V2.08  Empty line in ED problem (introduced in V2.07) fixed. Unset string parameter collapse in PRINT_USING fixed.

V2.09  PUTting randomly positioned bytes over the the network should not now shuffle the contents of a file.

V2.10  RENAME with only one name does not now leave file open. The file system prompts are now sent to #0 rather than channel 0.

V2.11  Initialisation error causing loss of replacement commands (e.g. OPEN) using JM/AH ROMs and CST QDisc V1.17 and V1.18 fixed.

V2.12  Bad error message return from opening a file name that is too long changed to return "bad name". "Bad parameter" from special job opening a file specified as a string in an EX command fixed. "Not complete" from SPL fixed. Last line recall changed to reduce problems due to asynchonous modification of keyboard queue.

V2.13  Error status returned from SAVE and LIST if drive full or bad or changed medium during output. Network fixed to prevent serial I/O buffer damage when interleaving serial I/O with window enquiries while reading from a file.

Appendix E: Floppy disk update Record

V1.07  (not released) Write operations held pending (up to 20 sectors). Direct sector IO added.

V1.08  Microdrive interleave problem with FS.LOAD call (in V1.07 only) fixed.

V1.09  Direct sector open does not now check the drive. On seek, the track register is set to the actual track number found on the track, seek errors will not be detected, so any track may be read from any part of the disk.

V1.10  Direct sector write in FM (*DnS) does not now give read/write failed (it did  work before though - just ignore the error message). This does not affect those interfaces which have MFM only. A fatal LOAD  error condition has been removed. This occurred in V1.07 onwards if:

1. a file is LOADed within .5  second of a modification to that file and;

2. the file was not closed or flushed in this period, and;

3. the directory entry for the file has become unreadable.

(There is no logical reason for conditions 1 and 2 to be met simultaneously!)

V1.11  Version 1.11 should be functionally identical to Version 1.10. The source code has been completely reorganised.

V1.12  The step rate detection procedure, which has not functioned well since version 1.09, has been fixed.

V1.13  The disk present detection routine has been changed to work reliably with index pulses as short as 10 us. (A problem with extreme out-of-spec Mitsubishi 3.5" drives.)

V1.14  The FLP_OPT command or the equivalent set of commands has been added. This now gives a choice of security versus speed, and extends the range of odd drives which may be used. The disk change detection has been redesigned and the disk header handling has been improved. The FORMAT procedure has been rewritten. It will not now detect step errors, but instead it formats and checks the disk in 5 revolutions per track (1 second, on double sided drives), or 3 revolutions per track (.6 second, on single sided drives). The check on the 11th character of a medium name (FORMAT) is not now done unless the name is at least 11 characters long. The error returns from direct sector reads have been tidied up. The read operations used in direct sector reads now have their own read error recovery. This should improve the reliability of direct sector reads (see V1.09 above). Direct sector reads no longer clear the read buffer before attempting to read. When checking for the presence of a disk, the driver now waits for just over one second before giving up. If there are repeated seek errors, the step rate is automatically reduced. The driver can now scatter load zero length files without getting in a knot.

V1.15  The changes in V1.15 are mainly to accomodate the 1772 control chip. Some of these may have beneficial side effects when using 1770 or 2793.

1. When first accessing a drive a check is made for 1772 step rates.

2. A compulsory 5ms settle is added after any seek: there was a  problem at 2ms step rate with premature termination of a restore command.

3. The unchecked seeks at the start of the format procedure and before a direct sector read / write are now performed at a slower step rate than the normal seeks. This should reduce the chances of an undetected seek error.

The sector allocation algorithm has been changed so that the first sector of a file may be allocated in track 0 when all other tracks are full. The internal messages have been moved to the base of the ROM.

Foreign language versions can now be made with simple patches. The write track  procedure (for  format) has  been changed  to improve the worst case timing margin.

V1.16  A problem with repeated checks  on a changed medium, when files are still open on a previous medium, has been fixed. The FLP_EXT command clears the procedure stack. RAM disk V1.02 incorporated where appropriate.

V1.17  RAM disk V1.03 incorporated where appropriate.

V1.18  Verify introduced on restore; additional pauses introduced on seek error recovery.

V1.19 to V1.25 Identical to V1.18

Appendix F: Index and List of Differences

This index lists the SuperBASIC extensions in alphabetical order together with the usage (procedure, function or program), the section number describing the facility in detail, the origin of the facility (whether the facility first appeared in the QL ROMs or in the Sinclair QL Toolkit) and principal differences between the facility in the Toolkit II and earlier versions.

This list only includes the most important differences, in many cases there are other improvements over earlier versions.

Name

Usage

Section

Origin

Differences

AJOB

procedure

9

QL Toolkit

accepts Job name

ALARM

program

18

QL Toolkit

resident program

ALCHP

function

15

QL Toolkit

ALTKEY

procedure

20

new

BGET

procedure

12

QL Toolkit

BIN

function

13

QL Toolkit

BIN$

function

13

QL Toolkit

BPUT

procedure

12

QL Toolkit

CALL

procedure

7

bug fix

CDEC$

function

13

QL Toolkit

CHAR_USE

procedure

14

QL Toolkit

CHAR_INC

procedure

14

QL Toolkit

CLCHP

procedure

15

QL Toolkit

CLEAR

procedure

6

QL

clears WHEN ERROR

CLOCK

program

18

QL Toolkit

configurable program

CLOSE

procedure

10

QL

close multiple files

CONTINUE

procedure

17

QL

specified line number

COPY

procedure

5

QL

uses default directory

uses default destination

COPY_O

procedure

5

new

overwrites file

COPY_N

procedure

5

QL

uses default directory

uses default destination

COPY_H

procedure

5

new

CURSEN

procedure

14

QL Toolkit

CURDIS

procedure

14

QL Toolkit

DATA_USE

procedure

4

QL Toolkit

DATAD$

function

4

new

DDOWN

procedure

4

new

DEL_DEFB

procedure

15

new

DELETE

procedure

5

QL

uses default directory

DEST_USE

procedure

4

new

DESTD$

function

4

new

DIR

procedure

5

QL

uses default directory

DLIST

procedure

4

new

DO

procedure

6

new

DNEXT

procedure

4

new

DUP

procedure

4

new

ED

procedure

3

QL Toolkit

completely respecified

ERR_DF

function

17

bug fix

ET

procedure

8

QL Toolkit

EX

procedure

8

QL Toolkit

EXEC

procedure

8

QL

now the same as EX

EXEC_W

procedure

8

QL

now the same as EW

EXTRAS

procedure

19

QL Toolkit

EW

procedure

8

QL Toolkit

FDAT

function

11

QL Toolkit

FDEC$

function

13

QL Toolkit

FEXP$

function

13

new

FLEN

function

11

QL Toolkit

FLUSH

procedure

12

new

FNAME$

function

11

new

FOP_DIR

function

10

QL Toolkit

finds vacant channel

FOP_IN

function

10

QL Toolkit

finds vacant channel

FOP_NEW

function

10

QL Toolkit

finds vacant channel

FOP_OVER

function

10

QL Toolkit

finds vacant channel

FOPEN

function

10

QL Toolkit

finds vacant channel

FPOS

function

12

QL Toolkit

FREE_MEM

function

15

QL Toolkit

gives 512 bytes less

FSERVE

program

22

new

FTEST

function

10

new

FTYP

function

11

QL Toolkit

FUPDT

function

11

new

FXTRA

function

11

new

GET

procedure

12

QL Toolkit

HEX

function

13

QL Toolkit

HEX$

function

13

QL Toolkit

IDEC$

function

13

QL Toolkit

JOB$

function

9

QL Toolkit

JOBS

procedure

9

QL Toolkit

LBYTES

procedure

7

QL

uses default directory

LOAD

procedure

6

QL

uses default directory

clears WHEN ERROR

LRESPR

procedure

7

new

LRUN

procedure

6

QL

uses default directory

clears WHEN ERROR

MERGE

procedure

6

QL

uses default directory

clears WHEN ERROR

MRUN

procedure

6

QL

uses default directory

clears WHEN ERROR

NEW

procedure

6

QL

clears WHEN ERROR

NFS_USE

procedure

22

new

NXJOB

function

9

QL Toolkit

OJOB

function

9

QL Toolkit

OPEN

procedure

10

QL

uses default directory

OPEN_DIR

procedure

10

new

uses default directory

OPEN_IN

procedure

10

QL

uses default directory

OPEN_NEW

procedure

10

QL

uses default directory

OPEN_OVER

procedure

10

new

uses default directory

PARNAM$

function

16

new

PARSTR$

function

16

new

PARTYP

function

16

QL Toolkit

PARUSE

function

16

QL Toolkit

PJOB

function

9

QL Toolkit

PRINT_USING

procedure

13

new

PROG_USE

procedure

3

QL Toolkit

PROGD$

function

3

new

PUT

procedure

12

QL Toolkit

RECHP

procedure

15

QL Toolkit

RENAME

procedure

5

QL Toolkit

RETRY

procedure

17

QL

specified line number

RJOB

procedure

9

QL Toolkit

accepts Job name

RUN

procedure

6

QL

clears WHEN ERROR

SAVE

procedure

6

QL

uses default directory

SAVE_O

procedure

6

new

overwrites file

SBYTES

procedure

7

QL

uses default directory

SBYTES_O

procedure

7

new

overwrites file

SEXEC

procedure

7

QL

uses default directory

SEXEC_O

procedure

7

new

overwrites file

SPJOB

procedure

9

QL Toolkit

accepts Job name

SPL

program

5

QL Toolkit

simplified destination

SPL_USE

procedure

4

QL Toolkit

SPLF

program

5

new

adds form feed to file

STAT

procedure

5

QL Toolkit

STOP

procedure

6

QL

clears WHEN ERROR

TK2_EXT

procedure

19

new

TRUNCATE

procedure

12

QL Toolkit

position may be specified

VIEW

procedure

3

QL Toolkit

WCOPY

procedure

5

new

defaults to command window

uses default destination

WDEL

procedure

5

QL Toolkit

defaults to command window

WDIR

procedure

5

QL Toolkit

WMON

procedure

14

QL Toolkit

WREN

procedure

5

new

defaults to command window

uses default destination

WSTAT

procedure

5

QL Toolkit

WTV

procedure

14

QL Toolkit

Table of Contents

Preface

1 Introduction

1.1 Commands Procedures Functions

1.2 Y/N/A/Q?

1.3 Overwriting

1.4 #channel

1.5 File and Device Names

1.6 CTRL F5

2 Contents of Toolkit II

2.1 Development Facilities

2.2 Command Language

2.3 SuperBASIC programming

2.4 Extensions to Devices

3 File Editing

3.1 ED - SuperBASIC Editor

3.2 Summary of Edit Operations

3.3 Viewing a file

4 Directory Control

4.1 Directory Structures

4.2 Setting Defaults

4.3 Directory Navigation

4.4 Taking Bearings

5 File Maintenance

5.1 Wild Card Names

5.2 Directory Listing

5.3 Drive Statistics

5.4 File Deletion

5.5 File Copying

5.5.1 Single File Copies

5.5.2 Wild Card Copies

5.5.3 Background Copying

5.5.4 Renaming Files

6 SuperBASIC Programs

6.1 DO

6.2 Default Directories

6.3 WHEN ERROR Problems

6.4 Common Heap

6.5 Summary of Commands

7 Load and Save

8 Program Execution

8.1 Single Program Execution

8.2 Filters

8.3 Example of Filter Processing

9 Job Control

9.1 Job Control Commands

9.2 Job Status Functions

10 Open and Close

10.1 Open Commands

10.2 File Status

10.3 File Open Functions

10.4 CLOSE

11 File Information

12 Direct Access Files

12.1 Byte I/O

12.2 Unformatted I/O

12.3 Truncate File

12.4 Flush Buffers

12.5 File Position

13 Format Conversions

13.1 PRINT_USING

13.2 Decimal Conversions

13.3 Exponent Conversion

13.4 Binary and Hexadecimal

14 Display Control

14.1 Cursor Control

14.2 Character Fount Control

14.3 Resetting the Windows

15 Memory Management

16 Procedure Parameters

17 Error Handling

18 Timekeeping

18.1 Resident Digital Clock

18.2 Alarm Clock

19 Extras

20 Console Driver

20.1 Keyboard Extensions

21 Microdrive Driver

21.1 Microdrive extensions

21.2 Microdrive Improvements

22 Network Driver

22.1 Network Improvements

22.2 File Servers

22.3 Accessing the File Server

22.4 Messaging

23 Writing programs to use with EX

23.1 Special Programs

Appendix A

Appendix B: QL Network Protocols

Appendix C: Toolkit II Code Sizes

Appendix D: Toolkit II Update Record

Appendix E: Floppy disk update Record

Appendix F: Index and List of Differences