|Z88 Developers' Notes|
13. Standard Input / Output and the CLI
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 GN_Sop write a string to standard output GN_Soe 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 outputInitially 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.
Sequence Significance # holding down <SQUARE> and pressing another key | holding down <DIAMON> 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 BASIC application) .* file Invoke a new CLI file .; CLI comment (rest of line until CR is ignore by CLI)NOTE: The CLI command '..' was intended to produce a single dot. This in fact does not work. Any number of dots at the start of the line will be ignored. One way around this bug 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
.main ld hl, cli_string ; string to pass the CLI ld c, 2 ; length ld b, 0 ; must be zero call_oz(DC_Icl) ; invoke a new CLI ld bc, 0 ; key read to allow CLI to be processed call_oz(OS_Tin) 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 call_oz(GN_Opf) ; open... jr nc, rebind call_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 call_oz(DC_Rbd) ; rebind to stream IX jr nc, continue call_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 call_oz(GN_Sop) ; output message to std. output and file ld ix, 0 ; close off CLI and file ld a, 4 ; T-output code call_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
|Integer arithmetic||Standard Input / Output and the CLI||The Printer filter|