The Z88 operating system has, at any one time, a standard input source and a standard output destination. A number of calls use these standard I/O streams:
OS_In read a character from standard input
OS_Tin timed read a character from standard output
OS_Out write a character to standard output
OS_Sout write a string to standard output
OS_Bout write a string at extended address to standard output
GN_Sip fetch an input line using standard I/O
GN_Sdo write date to standard output
Initially standard input and output are bound to the keyboard and screen respectively, but may be redefined to any file or device. The user may do this via the Command Line Interpreter (CLI). CLI commands are prefixed by a full stop and must be the first thing on the line.
.< INFILE take input from file/device "INFILE"
.> OUTFILE send output to file/device "OUTFILE"
which binds the standard input to "infile" and the standard output to "outfile". Redirection can also be done as T-fashion, where the ordinary streams remain in place, but copies of their contents are sent to a file or a device.
.T< INFILE send copy of input to file/device "INFILE"
.T> INFILE send copy of output to file/device "OUTFILE"
The printer output can be redirected in both ways:
.= PRTFILE redirect pre-filter printer output to file/device
.T= PRTFILE as .=, but also send the output to the printer filter.
Certain keystroke operations (such as <SQUARE> and <DIAMOND> sequences) have a special representation which is used when input is redirected. These sequences are generated when input is T-redirected and can be used in ordinary redirection to simulate the effect of the keyboard. Note that there are some keyboard features which have no representation, such as: the CAPS LOCK key, <SHIFT> or <DIAMOND> with <ESC>, the effect of holding down <SHIFT> and <DIAMOND> to stop output scrolling.
# holding down <SQUARE> and pressing another key
| holding down <DIAMOND> and pressing another key
~A pressing <SQUARE> and releasing it before another keypress
~C pressing <DIAMOND> and releasing it before another keypress
|[ <ESC> key
~E <ENTER> key
~S <SHIFT> key (only generated if <SHIFT> had an effect)
~I <INDEX> key
~M <MENU> key
~H <HELP> key
~X <DEL> key
~U <UP> arrow key
~D <DOWN> arrow key
~L <LEFT> arrow key
~R <RIGHT> arrow key
## a single # (hash) character
|| a single | character
~~ a single ~ tilde (pronounced 'tilda' or 'twiddle')
The CLI also has the following commands:
.S suspend the current CLI but maintain all rebindings
.D n delay for n centiseconds (if <ESC> is pressed during a delay then
subsequent delays will fail for the rest of the current CLI)
.J Jammer. Ignore all special sequences for the rest of the CLI (eg.
after this command #B will generate '#B' and try and enter a BBC
.* file Invoke a new CLI file
.; CLI comment (rest of line until CR is ignore by CLI)
NOTE: All CLI commands prefixed by a single dot must be at the start of a line. Any number of dots at the start of the line will be ignored. One way to produce a single dot is to use '~.' at the start of a line to generate a full stop. Subsequent dots (ie. ones which do not appear as the first character of the line) are treated like ordinary alpha characters.
CLI files can invoke other CLI files. A CLI file is terminated when the end of a file is reached or a suspension command is issued. CLI's can be forcibly removed one at a time by pressing <SHIFT> and <ESC>, or all current CLI's can be removed by using <DIAMOND> and <ESC>. Note that <DIAMOND> must be actually held down while <ESC> is pressed, ie. the usual latching operation does not apply. The CLI can be accessed by BBC BASIC by using the *CLI command or the OSCLI command. For example, to create a 10 second delay:
*CLI .D 100
OSCLI ("*CLI .D 100"): REM these two lines are equivalent
Most CLI use will be in the form of executable files, consisting of lines of CLI commands and text. These can be generated in PipeDream and saved as text files. Or generated by hand and then executed. CLI files can be executed from the FILER (using <>EX command) or from BBC BASIC using:
OSCLI ("*CLI .*"+fname$)
where fname$ contains the filename. Typical CLI files consist of short sequences like:
.T> copyout .S
The first line sends a copy of all output to the file 'copyout', and the second line maintains this new binding on exit from the CLI file. The binding (T-output to 'copyout') will now stay in place until the CLI is terminated by <SHIFT><ESC> to remove the current CLI (or <><ESC>, which removes all CLI's running). This situation will generally be undesirable, because it requires user intervention, since the program cannot simulate the effect of <SHIFT> <ESC>. Ideally the CLI should be avoided. Redirection can be easily achieved in applications by using file I/O, however, if necessary the CLI can be accessed fairly directly from an application. The operating system call DC_Icl invokes a new CLI, and is effectively the equivalent of BASIC's *CLI. The call DC_Rbd is used to directly rebind streams in the current CLI layer and can also terminate the CLI.
The program below starts a CLI, using DC_Rbd, rebinds the T-output stream, and finally closes the stream and terminates the CLI. Refer to "System Calls Reference" for details of the calls used:
include "director.def" ; director and CLI call definitions
include "stdio.def" ; standard I/O call defs. & parameters
include "fileio.def" ; standard file I/O call defs. & parameters
include "errors.def" ; error code calls and definitions
; entry point is .main
; on entry, (name) contains the address of a buffer which hold a filename
; to be used with the CLI, and (scratch) holds the address of a scratch
; buffer which need be no more than a few bytes in length
.main ld hl, cli_string ; string to pass the CLI
ld c, 2 ; length
ld b, 0 ; must be zero
oz DC_Icl ; invoke a new CLI
ld bc, 0 ; key read to allow CLI to be processed
ld b, 0 ; HL is a local address
ld hl, (name) ; filename
ld de, (scratch) ; address of scratch buffer
ld c, 1 ; explicit filename length
ld a, OP_OUT ; open a file for output
oz GN_Opf ; open...
jr nc, rebind
oz GN_Err ; display error in box
ret ; note that on exit the CLI will
; still be active
; code to rebind standard output
.rebind ld a, 4 ; T-output code
oz DC_Rbd ; rebind to stream IX
jr nc, continue
oz GN_Cl ; something has gone badly wrong
ret ; attempt to close the file and exit
; write to standard output, and hence also to the file
.continue ld hl, message
oz GN_Sop ; output message to std. output and file
ld ix, 0 ; close off CLI and file
ld a, 4 ; T-output code
oz DC_Rbd ; close file and quit CLI
ret ; return (ignore all errors)
.message defm "This should go to the file and the screen.", 0
.cli_string defm ".S", 0