BCPL For The BBC Microcomputer
BCPL For The BBC Microcomputer
BCPL e rG
for the BBC Microcomputer
uide
CHRIS JOBSON
and JOHN RICHARDS
R
O
IT
ED
6502 BCPL
CODE
Us
er
Gu
BCPL ide
for the BBC Microcomputer
CHRIS JOBSON
and JOHN RICHARDS
ACORNSOFT
Acknowledgement
We would like to thank Dr Tim King for his work in developing the
editor and relocatable assembler.
Disclaimer
FIRST EDITION
Published by:
Acornsoft Limited
4a Market Hill
Cambridge
CB2 3NJ
England
Contents
1 Introduction 1
How to use this guide 2
Features of the BCPL system 4
Computer requirements 12
3 Built in Commands 31
CONT - continue program 32
COPY - copy file 33
DELETE - delete file 34
END - end command file 34
ERRCONT - continue command file if error 35
INIT - initialise program for testing 36
LINK - link file into global vector 37
LOAD - format CINTCODE file for
linking 38
MODE - change display mode 39
PAUSE - suspend command file 40
PROTECT - hold file in store 41
READ - read file into store 42
REM (//) - comment 43
RENAME - rename file 44
SAVE - save store file 44
SHUFFLE - maximise contiguous free store 46
STORE - catalogue of store files 46
TIDY - free up store 48
TYPE - display text file 49
UNLINK - unlink file from global vector 50
4 Utilities 51
BCPL - the compiler 52
ED (& TED) - the editor 57
EX - execute command file 70
JOIN - join files 79
JOINCIN - join CINTCODE files 80
NEEDCIN - extract sections from library 81
RAS - the relocatable assembler 82
5 Procedures 85
(The chapter begins with a list of all
procedures and then describes them in
alphabetical order.)
11 Summaries 375
Assembler 376
Built in commands and utilities 378
CINTCODE 381
DEBUG commands 387
ED and TED commands 389
Error numbers and trap codes 392
Global variables 398
Global vector 400
Manifest constants 404
Procedures 406
Tape files 410
TESTPRO commands 411
Appendix 413
Running in the second 6502 processor 414
System data areas 414
System procedures 431
Use of operating system routines 435
Writing command-state programs 440
Index 443
l Introduction
This User Guide includes information needed by
every user of the Richards Computer Products BCPL
CINTCODE system on the BBC Microcomputer.
Overview
1
The programs and utilities include a general-
purpose full screen editor (which may be used for
letter and document writing as well as for program
entry), a BCPL compiler, a relocatable 6502 assem-
bler and a number of program development and de-
bugging tools. Indeed, the system may be used
just for its convenient file handling and editing
facilities.
2
Experienced users of BCPL who require a quick
reference to the features of this implementation
may use the summaries in chapter 11.
3
FEATURES OF THE BCPL SYSTEM
4
BCPL
CINTCODE
Compactness
5
CINTCODE is significantly more compact than UCSD
Pascal and Forth.
Portability
6
Code libraries
7
Store files
8
- alteration of store;
- symbolic traces;
Multi-tasking
9
Calculations
Speed
10
Relocatable machine code
Stand-alone programs
11
COMPUTER REQUIREMENTS
12
2 Using the BCPL System
This chapter is a brief guide to using the BCPL
system once it has been installed. Many of the
topics covered are explained in more detail else-
where in this manual. The installation of the
system is covered in chapter 9.
13
COMMANDS
!STORE
!DELETE myfile
!SAVE file1 AS file2
!*FX 7,4
!*TAPE
!*CAT
!ED textfile
!BCPL bprog cprog
!JOIN file1 file2 AS file3
14
which respectively edit the file named
‘textfile’, compile the BCPL source file
‘bprog’ to the CINTCODE file ‘cprog’ and join
the two files ‘file1’ and ‘file2’ to make a
new file ‘file3’.
15
WARNING: CTRL-V must not be used to change the
display mode since it may crash the system. The
correct way to change the display mode is to use
the built in command MODE described in chapter 3.
ARGUMENTS TO COMMANDS
16
For example the request:
!BCPL ?
FROM/A,TO/A,REPORT/K,NONAMES/S,MAX/S
17
COMMAND FILES
18
When a run-state program is active various events
can cause the system to suspend it and return to
the command state. When such an event has
occurred the user may invoke built in commands and
run any command-state program before resuming the
suspended program by the built in command CONT.
The user may also abandon the suspended program by
the built in command TIDY.
19
USE OF ESCAPE
20
DEVICES AND FILES
File names
21
Thus the following example of the built in command
COPY (described in chapter 3):
Device names
22
The input devices supported are:
/C the screen;
/L the printer;
/P the RS423 serial port.
!JOINCIN myfile AS /N
23
STORE FILES
24
A loaded file is one which is in the correct
format for execution. Either it is contiguous or
its block structure is such that each data block
contains exactly one section of CINTCODE (the
structure of CINTCODE is explained in chapter 10).
CINTCODE files not in the correct format are
automatically reformatted when they are run.
The built in commands LOAD and LINK also reformat
CINTCODE files if necessary.
25
STORE MANAGEMENT
- program stacks;
26
The first problem is solved by the TIDY procedure.
This procedure frees all allocated areas in the
heap except those in use for store files. It
is invoked automatically by the system when-
ever a program terminates normally, but is not
invoked if a program fails (since this might des-
troy valuable diagnostic information). The built
in command TIDY invokes the TIDY procedure.
27
OVERVIEW OF PROGRAM DEVELOPMENT
28
The program may use library procedures (from the
library file LIB or from a user-created appli-
cations library). These procedures must be
extracted from the library file and incorporated
into the program using the utility NEEDCIN.
29
30
3 Built in Commands
This chapter describes the built in commands con-
tained in the BCPL ROM. All these commands,
except PAUSE, may be used when there is an inter-
rupted program without affecting that program.
With the exceptions of CONT, INIT and TIDY these
commands may be invoked from within a program
using the procedure RUNPROG. If any command fails
an error number is displayed on the console (or
returned to the calling routine if RUNPROG was
used). The error numbers are listed in chapter
11. Chapter 2 describes how the arguments to the
commands are specified. The following commands
are described in this chapter (in alphabetical or-
der):
31
CONT - continue program
Purpose:
To continue execution of an interrupted
program.
Arguments:
None.
Example:
CONT
Remarks:
This command is used to continue a program
which has trapped to the command state. The
trap may have been caused by ESCAPE having
been pressed, by the program having run out of
heap space or by the program having called the
TRAP procedure.
32
COPY - copy file
Purpose:
To copy a file from one device to another or
to duplicate a file.
Arguments:
FROM/A,TO/A
Examples:
COPY file1 TO file2
COPY /P myfile
Remarks:
This command is a general purpose binary copy
which copies from any device/file to any other
device/file. For copying files from the cur-
rent filing system to store the READ command
should be used. For copying files from store
to the current filing system the SAVE command
should be used. For copying text files to the
screen or printer the TYPE command should be
used.
33
DELETE - delete file
Purpose:
To delete a file.
Argument:
FILE/A
Examples:
DELETE textfil
DELETE /F.myfile
Remarks:
FILE must be either a store file or a current
filing system file. If no device is specified
store is assumed.
Purpose:
To terminate processing of a command file.
Arguments:
None.
Example:
END
Remarks:
If this command is encountered in a command
file it terminates processing of that file.
34
ERRCONT - continue command file if error
Purpose:
To control the action to be taken if a program
being run from a command file fails.
Argument:
OFF/S
Examples:
ERRCONT
ERRCONT OFF
Remarks:
The normal action taken when a program being
run from a command file fails (i.e. terminates
with a positive error code) is to abandon the
command file. Issuing the command ERRCONT
overrides this default so that processing of
the command file will continue. ERRCONT may
be issued within the command file or it may be
typed in at the console before running a com-
mand file. Once ERRCONT has taken effect it
remains in effect until either ERRCONT OFF is
issued (from within the command file or at the
console) or the command file terminates.
35
If a program run from a command file ABORTs
then the command file is terminated regardless
of whether or not ERRCONT has been issued.
Purpose:
To initialise or reinitialise a program being
tested with DEBUG.
Arguments:
None, but the command is followed by arguments
for the program being tested.
Examples:
INIT
INIT file1 file2 AS file3
Remarks:
INIT initialises an already linked program so
that it can be run under DEBUG (see
chapter 7). For example the following se-
quence of commands might be used to run
JOINCIN (see chapter 4) under DEBUG:
!LINK JOINCIN
!INIT file1 file2 AS file3
!DEBUG
*0C
36
LINK - link file into global vector
Purpose:
To link a CINTCODE file to the global vector,
loading it and/or relocating it if necessary.
Arguments:
FILE,SYSTEM/S,LIBRARY/S
Examples:
LINK proga
LINK /F.newwrch SYSTEM
LINK LIBRARY
Remarks:
There are three variants of this command:
LINK file
LINK file SYSTEM
LINK LIBRARY.
37
The third variant relinks the ROM library.
It must be used before UNLINKing any SYSTEM
file containing alternative versions of any
library procedures. Note that this command
replaces all such alternative procedures by
the originals in ROM and so it may be desir-
able to relink all remaining SYSTEM files
after using this command.
Purpose:
To get a CINTCODE file into store in a suit-
able format for linking (i.e. either as a
contiguous file or with one CINTCODE hunk per
file block).
Argument:
FILE/A
Examples:
LOAD myprog
LOAD /F.abcde
Remarks:
If the specified file is already in store and
loaded then it is not reformatted. If the
file is in store but not loaded then a copy is
made in the correct format and the original
version is deleted. If the file is not in
store it is read into store (using the equiv-
alent of the command ‘READ file’) in the
correct format.
38
MODE - change display mode
Purpose:
To change the display mode.
Argument:
MODE/A
Example:
MODE 2
Remarks:
The heap is adjusted if possible to free the
memory needed for the requested display mode
and, if successful, the new display mode is
selected. Note that if the system is running
in the second 6502 processor (using the Tube)
then no adjustment of the heap is necessary.
39
The characteristics of the various modes are:
Purpose:
To suspend a command file.
Arguments:
None, but a message giving the reason for the
PAUSE may follow the command.
Example:
PAUSE Please load backup disk
Remarks:
When the PAUSE command is encountered in a
command file it is displayed on the console in
the normal way followed by the text:
40
PROTECT - hold file in store
Purpose:
To change the protection status of a store
file.
Arguments:
FILE/A,OFF/S
Examples:
PROTECT myprog
PROTECT tempfil OFF
Remarks:
Unprotected files, provided that they are
neither linked nor open, are deleted by the
built in command SHUFFLE and by one of the two
options of the library procedure SHUFFLE.
This library procedure may be called whenever
a vector is required from the heap (e.g. when
opening a stream, writing to a store file or
calling GETVEC).
41
READ - read file into store
Purpose:
To copy a file from the current filing system
into store or to copy a store file to another
store file.
Arguments:
FILE/A,AS=ON=TO
Examples:
(1) READ myfile
(2) READ /F.file1 AS file2
(3) READ /S.abcde ghijk
(4) READ afile TO bfile
Remarks:
The normal use of this command is to copy a
file from the current filing system to a store
file of the same name. Thus example (1) would
copy the file ‘myfile’ from the current filing
system into store. Note that the name
specified should not contain a device prefix.
The command READ /F.myfile would look for a
file named ‘/F.myfile’ on the current filing
system.
42
When copying from the current filing system
this command is faster than COPY.
Purpose:
To allow comment lines to be typed at the
console or to be included in command files.
Arguments:
None.
Examples:
REM This is a comment
// and so is this
Remarks:
The rest of the line is ignored. Note that
there must be at least one space between REM
or // and the text following it.
43
RENAME - rename file
Purpose:
To rename store files and current filing
system files.
Arguments:
FROM/A,TO/A
Examples:
RENAME file1 TO file2
RENAME /F.data olddata
Remarks:
The device to be used (store or current filing
system) is taken from the FROM name. If no
device is specified then store is assumed.
The TO name must not contain a device
specifier.
Purpose:
To copy a store file to the current filing
system or to some other device.
Arguments:
FILE/A,AS=ON=TO
Examples:
(1) SAVE myfile
(2) SAVE datafil TO /P
(3) SAVE filea /F.fileb
(4) SAVE afile AS bfile
44
Remarks:
The normal use of this command is to copy a
store file to a file of the same name on the
current filing system. To achieve this only
one file name is specified. This file name
must not include a device specifier. Thus
example (1) copies the store file ‘myfile’ to
the current filing system file ‘myfile’. The
command SAVE /S.myfile would copy the store
file named ‘/S.myfile’ to a filing system file
with the same name.
45
A SAVE to the current filing system does not
set up the file’s load or execution address.
Purpose:
To rearrange the heap so that as far as
possible the free areas are made contiguous.
Arguments:
None.
Example:
SHUFFLE
Remarks:
All unprotected store files are deleted and
then the remaining unlinked files are moved
down in the heap so that the free space is
concentrated at the top of the heap.
Purpose:
To give a catalogue of the files in store and
an indication of how much free space is left
in the heap.
Arguments:
None.
Example:
STORE
Remarks:
This command produces a two-part display.
The first part is a catalogue of the store
files. The second part summarises the space
available.
46
The order of the files in the catalogue is not
significant. The following information is
displayed for each file:
47
TIDY - free up store
Purpose:
To restore the system to a tidy state after a
program has completed.
Arguments:
None.
Example:
TIDY
Remarks:
If a program completes successfully the system
automatically performs a TIDY. If a program
fails, however, a TIDY is not performed so
that the user can obtain as much information
as possible about the failure. Thus TIDY
should be used when all such information has
been obtained. TIDY may also be used to
abandon an interrupted program (note that if
the interrupted program was run from a command
file then that command file will also be aban-
doned unless ERRCONT is in effect).
48
TYPE - display text file
Purpose:
To display a text file on the console or some
other device.
Arguments:
FILE/A,AS=ON=TO
Examples:
(1) TYPE text
(2) TYPE /F.myprog ON /L
Remarks:
If the second parameter is omitted (as in
example (1)) the FILE is displayed on the
console, otherwise it is copied to the
specified device. Thus example (2) copies the
file ‘MYPROG’ from the current filing system
to the printer.
49
UNLINK - unlink file from global vector
Purpose:
To unlink a CINTCODE file from the global
vector.
Argument:
FILE/A
Example:
UNLINK MYPROG
Remarks:
If the file is not linked no action is taken.
If the file is linked then it is unlinked and
any assembler hunks are unrelocated. The
file is left loaded.
50
4 Utilities
This chapter describes the utility programs pro-
vided with the BCPL system. These permit the
development of BCPL and assembler programs. Chap-
ter 2 describes how the arguments to a utility are
specified.
51
BCPL - the compiler
Purpose:
To compile source text written in BCPL into
CINTCODE which can be run by the BCPL system.
Examples:
(1) BCPL myfile mycode
(2) BCPL /F.bfile cfile MAX REPORT=/L NONAMES
Arguments:
FROM/A,TO/A,REPORT/K,NONAMES/S,MAX/S
Function:
The utility compiles from the source file FROM
to the CINTCODE file TO. Thus example (1)
will compile from ‘myfile’ to ‘mycode’. Chap-
ter 10 describes the features of the language
BCPL.
REPORT
REPORT reportfile
52
NONAMES
MAX
53
Remarks:
The compiler can be interrupted by pressing
ESCAPE.
54
Compilation Size
55
Compiling from tape
BCPL
BCPLARG
BCPLSYN
LIBHDR // the library header file
BCPLTRN
BCPLCCG
56
ED (& TED) - the editor
Purpose:
To create and edit text files.
Examples:
ED txtfile
TED newfile NEW
Arguments:
FROM/A,NEW/S
Function:
The editor may be used to create a new file,
or to alter an existing one. The text is
displayed on the screen, and may be scrolled
vertically or horizontally as required.
57
Editor commands fall into two categories
immediate commands and extended commands.
58
Starting and stopping
59
It is possible to stop without creating the
output file (if a mistake has been made during
the editing, for example) by f9. If no
changes have been made to the file the editor
just exits, otherwise it prompts for
confirmation (to prevent accidentally losing
changes).
Interrupting
Text entry
60
If text is typed past column 253 then a new
line is automatically inserted before the
current word. In ED the column at which this
occurs can be changed by the extended command
RM.
Cursor movement
61
CTRL-f3 move cursor to first character in
file;
CTRL-f4 move cursor to first character in
last line of file.
Text deletion
62
Miscellaneous immediate commands
63
Entering a control character or pressing any
function key (except f0) while in extended
mode returns immediately to immediate mode.
64
Cursor movement with extended commands
65
E/s/t/ search the file, starting with the
character at the cursor position, for
the string s. If found replace it
with the string t and leave the cur-
sor at the next character. If not
found leave the cursor at its orig-
inal position;
EQ/s/t/ same as the command E but ask for
confirmation from the user before
performing the substitution (if the
substitution is not performed leave
the cursor at the character beyond
the matching string s in the file);
F/s/ search the file, starting with the
character to the right of the cursor
position, for the string s. If found
leave the cursor at the start of the
matching text. If not found leave
the cursor at its original position.
66
A block can be hidden. When a block is hidden
it is not marked on the screen and the copy,
move and delete facilities do not work. The
cursor may still be moved to the block start
and block end however. This mode is useful to
prevent accidental block deletion when using
the block facility just as two line markers.
File handling
67
WB/f/ write the current block as file f. If
the file already exists it is over-
written.
Formatting text
68
Tab stops may be set:
Repeating commands
69
Groups of commands may be repeated by en-
closing the group in curved brackets. For
example, the following extended command re-
places every third occurrence of ‘abc’ by
‘def’:
T;RP(3F/abc/;E/abc/def/)
Purpose:
To start execution from a command file. The
command file is created from an exfile which
provides a template which may be modified by
the arguments to the EX utility.
70
Examples:
EX exfile
EX compile FROM mysrce TO myprog
Arguments:
The first argument is the name of the exfile.
The remaining arguments are interpreted
according to the .KEY directive in the exfile
(see below).
Function:
EX copies the exfile to a temporary store file
(named ‘$$EX’) then exits leaving this
temporary file as a command file to be ex-
ecuted. The system deletes the temporary file
when it has finished with it (i.e. either when
the end of the file is reached or when ex-
ecution of the file is terminated for some
other reason).
Format of exfiles
71
The following directives exist:
.KEY arguments
This specifies the argument definitions
used to interpret the EX command line.
The arguments are in the format used by
the library procedure RDARGS, but every
parameter should be given a keyword.
There may be at most one .KEY directive in
an exfile.
.DEF keyword=value
This specifies a value to be associated
with a keyword if the corresponding
argument is omitted from the EX command
line. If more than one .DEF directive is
specified for the same keyword all but the
first are ignored.
.BRA character
Redefines the character indicating the
start of a keyword within a normal line
(initially ‘<’).
.KET character
Redefines the character indicating the end
of a keyword within a normal line (init-
ially ‘>’).
.DOT character
Redefines the character introducing a
directive (initially ‘.’).
72
Examples
(1) No substitution
EX mycmds
.KEY FILE1/A,FILE2/A,PROG/A
BCPL b.<FILE1> c.<FILE1>
BCPL b.<FILE2> c.<FILE2>
JOINCIN c.<FILE1> c.<FILE2> AS c.<PROG>
73
Note that in this example all the keywords
have the qualifier ‘/A’ meaning that the
corresponding argument must be present.
.KEY PROG/A,FILE1/A,FILE2,FILE3
JOINCIN <FILE1> <FILE2> <FILE3> AS <PROG>
The command
.KEY FROM/A,TO/A,LIB
.DEF LIB=mylib
NEEDCIN <FROM> <LIB> <TO>
When executed by
74
But when executed by
.KEY ARG1,ARG2
.DOT #
.KEY This is a normal line
#BRA (
#KET ]
<ARG1> is not substituted
BCPL (ARG1] (ARG2]
#DOT .
.KET )
(ARG2)<ARG2>
75
The .DOT directive indicates that subsequent
directives begin with ‘#’ rather than ‘.’.
Thus the line beginning ‘.KEY This’ is not
treated as a directive. The next two lines
redefine ‘<’ as ‘(‘ and ‘>’ as ‘]’. The
#DOT directive restores ‘.’ as the character
introducing a directive and the .KET directive
therefore redefines ‘]’ as ‘)’.
Remarks:
76
If a program being run from a command file
terminates by calling ABORT then the command
file is terminated. If a program terminates
by FINISH, calling ENDPROG or returning from
START then the next command in the file is
executed. If a program terminates by calling
STOP then the result depends on the parameter
to STOP.
77
If ESCAPE is used to interrupt a trap-state
program or command (e.g. COPY) being run from
a command file then if ERRCONT is not in
effect it abandons the command file. If
ERRCONT is in effect then it sets LASTERROR to
1017 and resumes the command file with the
next command.
.KEY FILE/A,PROG/A,COMPILE
<COMPILE> BCPL b.<FILE> c.<FILE>
NEEDCIN c.<FILE> mylib c.<PROG>
78
Terminating a command file
Purpose:
To join two or more files to create a larger
file.
Example:
JOIN file1 /F.file2 file3 AS bigfile
Arguments:
FROM/A,,,,,,,,,,,,AS=TO/A/K
Function:
JOIN joins up to 12 files together to make one
big file. The joined file is given the name
specified after the AS (or TO) keyword, which
must be present.
Remarks:
The output file must not be the same file as
any of the input files.
79
JOINCIN - join CINTCODE files
Purpose:
To join two or more CINTCODE compatible files
to create a larger file, which can be loaded
as one segment. It may also be used to add
procedures to an existing CINTCODE program.
Example:
JOINCIN segment1 segment2 segment3 AS myprog
Arguments:
FROM/A,,,,,,,,,,,,AS=TO/A/K
Function:
JOINCIN joins up to 12 CINTCODE files. The
resulting file is given the name specified by
the AS (or TO) keyword, which must be present.
Remarks:
The output file must not be the same file as
any of the input files.
JOINCIN myfile /N
80
NEEDCIN - extract sections from library
Purpose:
To satisfy NEEDS directives in a CINTCODE
file by adding the required sections from a
file acting as a library.
Examples:
(1) NEEDCIN mycode mylib myprog
(2) NEEDCIN sega AS /N
Arguments:
FROM/A,LIBRARY,AS=TO/A
Function:
NEEDCIN copies the FROM file to the TO (or AS)
file, examining the NEEDS directives in it as
it does so. If any NEEDS remain unsatisfied
it then opens the LIBRARY file (if one is
specified) and searches it for the sections
needed. These sections are appended to the TO
file, and any unsatisfied NEEDS directives
they contain are added to the list of sections
required.
Remarks:
The structure of a LIBRARY file is identical
to that of any other CINTCODE segment (see
chapter 10). Thus files can be created for
use as library files by JOINCIN. The library
file provided with the system is LIB.
81
NEEDCIN can be used as a general method
of extracting specified sections from a
CINTCODE file. A segment is created con-
taining NEEDS directives for the re-
quired sections, and NEEDCIN is applied to
this segment specifying the CINTCODE file as
the LIBRARY file.
Purpose:
To assemble 6502 machine code to a relocatable
format that can be used in the BCPL environ-
ment.
Examples:
RAS myass TO mycode
RAS mysrc1 mysrc2 TO mycode LIST /L
Arguments:
FROM/A,,,,,,,,,,TO=AS/A/K,LIST/K
82
Function:
The assembler source in the FROM files is
assembled to CINTCODE in file TO. Up to ten
source files may be specified. The assembler
produces output compatible with the BCPL
CINTCODE system, and can be used to supply
assembler routines which can be accessed from
BCPL as described in chapter 8. Special
facilities are provided to access BCPL global
variables, and to supply section and procedure
names.
83
84
5 Procedures
This chapter describes the library procedures
provided with the BCPL CINTCODE system. The
procedures are in alphabetical order.
BACKMOVE BACKMVBY
INPUT
NEWLINE NEWPAGE
85
OPSYS OUTPUT
PACKSTRING PUTBYTE
86
ABORT
Purpose:
To end a program which has detected an error
condition from which it cannot recover.
Examples:
ABORT( aborttype)
IF address=0 DO ABORT( 533)
Function:
Unless the program is trapping ABORTs (see
Remarks below) then the program is terminated.
If the program was run from the console a
message of the form
Abort nnn
Remarks:
Abort codes 1−499 and 1000−1255 are reserved
for system use. Applications may use all
other possible codes.
87
Certain programs may wish to trap ABORTs. It
is possible to intercept ABORT calls by
setting the globals ABORTLEVEL and ABORTLABEL.
ABORTLEVEL should be set by a command such as:
ABORTLEVEL := LEVEL()
Portability:
The procedure is found in other BCPL implemen-
tations, but the provision to trap ABORT
calls is specific to this implementation.
88
ADVAL
Purpose:
To provide a convenient interface to the ADVAL
call in the operating system.
Examples:
(1) chn1val := ADVAL(1) >> 1
(2) chars.in.buff := ADVAL(−1)
Function:
To issue an OSBYTE call with parameter #X80
and return the result of the call.
89
A parameter in the range −1 to −9 returns the
number of characters in an input buffer or the
number of free spaces in an output buffer.
The buffer numbers are:
−1 keyboard
−2 RS423 input
−3 RS423 output
−4 printer
−5 to −8
sound channels 0 to 3
−9 speech.
Remarks:
Further information on the operation of ADVAL
is given in the BBC Microcomputer User Guide.
Portability:
Specific to this implementation.
90
APTOVEC
Purpose:
To call a procedure and to provide it with a
vector whose size is chosen at runtime. The
vector is obtained from the stack.
Example:
res := APTOVEC( f, n)
Function:
The procedure f is called with two arguments,
the vector and the size n. The result is the
value, if any, returned by the call of f.
The operation could be described in (illegal)
BCPL as:
Remarks:
If there is not enough room for a vector of
size n in the stack, APTOVEC calls ABORT.
The procedure STACKSIZE may be used to check
the stack space available before calling
APTOVEC.
91
The disadvantage of using APTOVEC is that
enough stack space must be allocated to the
program to allow for the biggest possible
vector that may be required.
Portability:
A standard procedure.
BACKMOVE
Purpose:
To provide a rapid transfer of a block of
words from one store location to another.
Example:
BACKMOVE( fromaddr, toaddr, words)
Function:
The block of length words words starting at
word fromaddr is copied to a block starting at
word toaddr, moving the last word in the block
first.
Remarks:
If the two blocks do not overlap this pro-
cedure is equivalent to MOVE. If they do
overlap then BACKMOVE should be used for mov-
ing up in store and MOVE for moving down.
Portability:
Developed for this implementation.
92
BACKMVBY
Purpose:
To provide a rapid transfer of a block of
bytes from one store location to another.
Example:
BACKMVBY( frombyaddr, tobyaddr, bytes)
Function:
The block of length bytes bytes starting at
byte frombyaddr is copied to a block starting
at byte tobyaddr, moving the last byte in the
block first.
Remarks:
If the two blocks do not overlap this pro-
cedure is equivalent to MOVEBYTE. If they do
overlap then BACKMVBY should be used for mov-
ing up in store and MOVEBYTE for moving down.
Portability:
Developed for this implementation.
93
CALL
Purpose:
To call assembly language procedures which are
located at a word address.
Example:
result := CALL( wordaddress, argument1,
argument2)
Function:
The CALL procedure generates a 6502 machine
code call to the specified word address, with
argument1 in register A and argument2 in
registers Y and X, with X holding the least
significant byte.
Remarks:
If the called machine code has been generated
by the relocatable assembler, and the entry
point has been declared as a global, then
CALL can use the global to specify the
wordaddress.
94
Portability:
This feature is similar to the language exten-
sion A15, but the declaration of wordaddress
by EXTERNAL is not supported.
CALLBYTE
Purpose:
To call assembly language procedures at a byte
address.
Example:
result := CALLBYTE( byteaddress,argument1,
argument2)
Function:
The CALLBYTE procedure generates a 6502
machine code call to the specified byte add-
ress. The parameter passing and return con-
ventions are identical to those for CALL de-
scribed above.
Remarks:
This procedure is intended for calling machine
code procedures which have not been created by
the relocatable assembler, and which have
fixed entry points which may be on an odd byte
address (e.g. the operating system routines
OSWORD, OSCLI etc.).
Portability:
This feature is similar to the language exten-
sion A15, but the declaration of byteaddress
by EXTERNAL is not supported. It may be de-
clared as a MANIFEST if required.
95
CALLCO
Purpose:
To transfer control to another coroutine,
passing a parameter, and to receive control
back again with a reply.
Example:
reply := CALLCO( coroutine, parameter)
Remarks:
This procedure is included in section "CORTNS"
of the CINTCODE library file LIB.
Portability:
Part of the published method of implementing
coroutines in BCPL.
CAPCH
Purpose:
To convert any alphabetic character to upper
case, while any other character is returned
unaltered.
Examples:
capital.char := CAPCH( character)
WHILE 'A' <= CAPCH(ch) <= 'Z' DO
Portability:
An equivalent procedure is provided on many
systems; in some systems it is called
‘capitalch’.
96
COMPCH
Purpose:
To compare two ASCII characters.
Example:
comparison := COMPCH( character1, character2)
Function:
To find if two characters are the same,
ignoring the differences between upper and
lower case. COMPCH is also useful when sort-
ing characters.
Remarks:
The comparison is:
Portability:
This procedure is provided on other BCPL sys-
tems.
COMPSTRING
Purpose:
To compare two ASCII strings.
Example:
comparison := COMPSTRING( string1, string2)
97
Function:
To find if two strings are the same, ignoring
the differences between upper and lower case
alphabetic characters. COMPSTRING is also
useful when sorting strings into lexical
order.
Remarks:
The comparison is:
Portability:
This procedure is provided on other BCPL
systems.
COWAIT
Purpose:
To suspend a coroutine at a suitable stage,
and to wait for reactivation.
Example:
parameter := COWAIT( reply)
Function:
The reply will be returned to the parent co-
routine, and the parameter will be provided
when the waiting coroutine is reactivated.
Portability:
Part of the published method of implementing
coroutines in BCPL.
98
CREATECO
Purpose:
To create a coroutine, with a given entry
point and stack size.
Example:
coroutine := CREATECO( procedure, stacksize)
Function:
The coroutine is the reference to be used for
the created coroutine. It is zero if the co-
routine could not be created for lack of store
(note that this can only happen if the program
has disabled trapping to the command state on
GETVEC failure - see chapter 6).
Portability:
Part of the published method of implementing
coroutines in BCPL.
99
DELETECO
Purpose:
To delete a coroutine.
Examples:
is.successful := DELETECO( coroutine)
DELETECO( coroutine)
Function:
The coroutine’s stack is returned to free
store. The result returned is FALSE if the
coroutine does not exist. DELETECO ABORTs if
the coroutine is the current coroutine or a
parent or ancestor of the current coroutine.
Remarks:
Since DELETECO will not fail if given a non-
existent coroutine, it is possible to use a
common re-initialising routine, which de-
letes all possible coroutines.
Portability:
Part of the published method of implementing
coroutines in BCPL.
DELFILE
Purpose:
To delete a file.
Examples:
DELFILE( filename)
is.successful := DELFILE( "/F.myfile")
Function:
An attempt is made to delete the file identi-
fied by filename.
100
If the deletion succeeds the result is TRUE.
If it fails the result is FALSE and RESULT2
contains the appropriate error code.
Remarks:
If the filename does not contain a device
specifier then the name is treated as the name
of a store file. To delete a store file whose
name begins with ‘/’ the store file prefix
‘/S.’ must be used.
Portability:
Similar functions are provided on other BCPL
systems.
DELXFILE
Purpose:
To delete a file on a specified device.
Examples:
(1) DELXFILE( filename, device)
(2) is.successful := DELXFILE( "myfile", DV.F)
(3) DELXFILE( "/F.storefile", DV.S)
Function:
An attempt is made to delete the file identi-
fied by filename on the device identified by
device. Device may be ‘DV.F’ to specify the
current filing system or ‘DV.S’ to specify the
store filing system.
101
If the deletion succeeds the result is TRUE.
If it fails the result is FALSE and RESULT2
contains the appropriate error code.
Remarks:
This procedure is useful for deleting a file
when the device is known, without having to
manipulate filename strings to include a
device prefix.
Portability:
Specific to this implementation.
102
ENDPROG
Purpose:
To provide the user with the option of ending
the program.
Example:
ENDPROG( endcheck)
Function:
If endcheck is TRUE a message is displayed as
follows:
Remarks:
If there is no doubt that the program is to be
stopped, the procedure STOP is appropriate.
ENDPROG simplifies the handling of cases when
a program end may have been requested by acci-
dent.
Portability:
Developed for this implementation.
103
ENDREAD
Purpose:
To close the current input stream. If the
current input stream is from a file then this
procedure closes the file.
Example:
ENDREAD()
Remarks:
Note that in order to close a stream it must
be selected.
Portability:
Standard BCPL procedure.
ENDWRITE
Purpose:
To close the current output stream. If the
current output stream is to a file then this
procedure closes the file.
Example:
ENDWRITE()
Remarks:
Note that in order to close a stream it must
be selected.
104
When a program terminates the system auto-
matically closes all open streams, but it is
good practice to explicitly close output
streams since if the system fails with files
open these files may not be recoverable.
Portability:
Standard BCPL procedure.
ENVELOPE
Purpose:
To define an envelope for use with the SOUND
facility of the BBC Microcomputer.
Example:
LET envtab = TABLE 1,1,4,−4,4,10,20,10,127,
0,0,−5,126,126
ENVELOPE( envtab)
Function:
The parameter is a fourteen-word table or
vector containing the fourteen parameters
defining an envelope. The envelope is com-
pacted into a seven-word area and passed to
the operating system using the OSWORD call.
Details of the envelope parameters are given
in the BBC Microcomputer User Guide.
Remarks:
This procedure is provided mainly for ease in
converting BASIC programs to BCPL. In many
cases it will be easier to make the OSWORD
call directly using CALLBYTE.
Portability:
Specific to this implementation.
105
ERRORMSG
Purpose:
To generate an error or warning message on the
console, normally when a program terminates
with a non-0 parameter to STOP.
Example:
ERRORMSG( stopcode)
Function:
If stopcode is 0 no action is taken.
Remarks:
This procedure is mainly intended for system
use (it is called whenever a program term-
inates), but it may be of use to application
programs e.g. to report the result of RUNPROG.
106
Users may wish to write their own versions of
the procedure, e.g. to generate text messages
for some or all of the system error codes.
Portability:
Specific to this implementation.
EXTSFILE
Purpose:
To extend a store file with data contained in
a vector.
Examples:
(1) is.successful := EXTSFILE( name, vector)
(2) v := GETVEC(30) // any size >= 9 OK
MOVE(data, v+2, 8) // 16 bytes of data
v!1 := 16
is.successful := EXTSFILE("myfile", v)
Function:
Name is a string which is taken to be the name
of a store file (thus "/F.myfile" is not
interpreted as a file on the current filing
system but as a store file called
‘/F.myfile’).
107
Vector must be set up as follows:
Remarks:
This procedure is convenient for adding data
to the end of an existing store file. (The
only other way to extend a file is to open it
for read, copy it completely to a new file,
write the new data, delete the old file and
rename the new file to the name of the old
file.)
Portability:
Specific to this implementation.
108
FILETOVEC
Purpose:
To convert a file into a vector. If the file
is a store file it is deleted by the con-
version.
Examples:
vector := FILETOVEC( string)
vector := FILETOVEC("/F.fileb")
Function:
String is interpreted in the normal way. Thus
"/S.myfile" refers to a store file,
"/F.myfile" to a current filing system file
and "myfile" to a store file if there is one
else a current filing system file.
Remarks:
The vector allocated is just big enough to
contain all the data and so the program must
not attempt to write past the end of the data
in the vector. It is the responsibility of
the program to free the vector (by FREEVEC)
when it has finished with it (although the
system frees all vectors when the program
terminates).
109
String must specify either a store file or a
current filing system file. Other devices
(e.g. ‘/P’) are not allowed. The file must
not be open or linked.
Portability:
Specific to this implementation.
FINDARG
Purpose:
To find if a given string is one of a small
number of specified keywords.
Examples:
argumentno := FINDARG( keys, string)
dev := FINDARG("N,C,K,L,P,F,S", devname)
Function:
The keys are specified in a string, separated
by commas. If the string matches one of the
keys the result returned is the argument num-
ber, starting with 0 for the first argument.
If no match is found the result is −1.
Remarks:
All comparisons ignore the differences between
upper and lower case. Thus a key "abCD"
would be matched by the string "AbcD".
comp := FINDARG("EQUAL=EQU=EQ,NOTEQUAL=NE",
string)
110
Each key may also be qualified, normally for
other purposes, if the qualifiers follow the
key after a ‘/’. Thus the following call
might arise from RDARGS.
comp := FINDARG("FROM/A,,,,,,,,TO,CHECKING/S",
string)
Portability:
This procedure is provided on other BCPL sys-
tems.
FINDINPUT
Purpose:
To initialise a stream for reading. If the
string specifies a file this corresponds to
opening the file for input.
Examples:
stream := FINDINPUT( string)
consoleinput := FINDINPUT( "/C")
sysinput := FINDINPUT( "myfile")
discinputb := FINDINPUT( "/F.fileb")
Function:
The string identifies the stream to the BCPL
system. The result of the function is a
value which represents the stream and may be
used by SELECTINPUT.
111
Remarks:
String is interpreted in the normal way. Thus
"/S.myfile" refers to a store file,
"/F.myfile" to a current filing system file
and "myfile" to a store file if there is one
else a current filing system file.
Portability:
Standard BCPL procedure, but the format of
stream names is specific to this system.
FINDOUTPUT
Purpose:
To initialise a stream for writing. If the
string specifies a file this corresponds to
opening the file for output.
Examples:
stream := FINDOUTPUT( string)
consoleoutput := FINDOUTPUT( "/C")
sysoutput := FINDOUTPUT( "myfile")
discoutputb := FINDOUTPUT( "/F.fileb")
Function:
The string identifies the stream to the BCPL
system. The result of the function is a
value which represents the stream and may be
used by SELECTOUTPUT.
112
Remarks:
String is interpreted in the normal way. Thus
"/S.myfile" and "myfile" both refer to a store
file and "/F.myfile" refers to a current
filing system file.
Portability:
Standard BCPL procedure, but the format of
stream names is specific to this system.
FINDXINPUT
Purpose:
To open a file on a specific device for input.
Examples:
(1) stream := FINDXINPUT( string, device)
(2) stinp := FINDXINPUT( "/F.myfile", DV.S)
(3) fsinputb := FINDXINPUT( "fileb", DV.F)
Function:
The string is treated as a ‘pure’ file name
i.e. it is not checked for starting with a
device specifier. Device must be either
‘DV.F’ to specify the current filing system or
‘DV.S’ to specify the store filing system.
The result of the function is a value which
represents the stream and may be used by
SELECTINPUT.
113
Remarks:
This procedure is useful for opening a file
when the device is known, without having to
manipulate filename strings to include a
device prefix. Note that example (2) above
opens a store file named ‘/F.myfile’ whereas
FINDINPUT("/F.myfile") opens a current filing
system file named ‘myfile’.
Portability:
Specific to this implementation.
114
FINDXOUTPUT
Purpose:
To open a file on a specific device for
output.
Examples:
(1) stream := FINDXOUTPUT( string, device)
(2) stinp := FINDXOUTPUT( "/F.myfile", DV.S)
(3) fsinputb := FINDXOUTPUT( "fileb", DV.F)
Function:
The string is treated as a ‘pure’ file name
i.e. it is not checked for starting with a
device specifier. Device must be either
‘DV.F’ to specify the current filing system or
‘DV.S’ to specify the store filing system.
The result of the function is a value which
represents the stream and may be used by
SELECTOUTPUT.
Remarks:
This procedure is useful for opening a file
when the device is known, without having to
manipulate filename strings to include a
device prefix. Note that example (2) above
opens a store file named ‘/F.myfile’ whereas
FINDOUTPUT("/F.myfile") opens a current filing
system file named ‘myfile’.
115
FINDXOUTPUT is declared in SYSHDR.
Portability:
Specific to this implementation.
FREEVEC
Purpose:
To return a vector obtained by GETVEC to free
store.
Example:
FREEVEC( vector)
Remarks:
FREEVEC will accept a parameter 0 without
complaint. It is thus possible to use a
common re-initialising routine which returns
all possible vectors, provided the vector
pointers are initialised to zero. If vector
is neither zero nor a valid allocated vector,
FREEVEC calls ABORT.
Portability:
Part of extension A7 to the standard language.
116
FSTYPE
Purpose:
To provide information on the characteristics
of the current filing system.
Examples:
characteristic := FSTYPE( mask)
osgbpb.avail := FSTYPE(1)
Function:
The current filing system number is determined
by calling the operating system routine OSARGS
with the A and Y registers both 0. This
number is used to access a set of flags
indicating the filing system characteristics
and these flags are copied into the global
MCRESULT.
117
32 the BCPL system should display
‘opening file xxx’ messages when
opening files.
Remarks:
This procedure is intended for use by the
system to determine the actions it should take
when opening/accessing files on the current
filing system. It is not anticipated that
application programs will need to call this
procedure.
Tape 1, 2 4 + 8 + 32 (=44)
ROM 3 16
Disk 4 1 + 2 (=3)
Econet 5 1 + 2 (=3)
Others 0
Portability:
Specific to this implementation.
118
GETBYTE
Purpose:
To obtain a byte from a string.
Example:
byte := GETBYTE( string, byteposition)
Remarks:
Since the introduction of the % operator the
function of GETBYTE is better provided by:
byte := string%byteposition
Portability:
A standard procedure.
GETVEC
Purpose:
To obtain a vector from free store.
Examples:
vector := GETVEC( vectorsize)
datastore := GETVEC( 1000)
Function:
This procedure obtains a contiguous area of
store of vectorsize + 1 words, (so that
vector!0 and vector!vectorsize are available).
119
GETVEC returns a pointer to the vector
address, i.e. the first word. If enough store
is not available GETVEC calls SHUFFLE to re-
arrange the store files then tries again. If
there is still not enough room it calls
SHUFFLE to delete all unprotected store files
and re-arrange those remaining then tries once
more. If it has still not succeeded the
action taken depends on the system state.
Remarks:
The free store is organised in the area known
as the heap. If GETVEC finds the organ-
isation of this area is corrupt it calls
ABORT.
120
The procedure MAXVEC may be used to check the
largest vector available before calling
GETVEC.
Portability:
Part of extension A7 of the standard language.
GLOBIN
Purpose:
To link already loaded CINTCODE into the glo-
bal vector.
Examples:
is.successful := GLOBIN( segment)
GLOBIN( LOADSEG( codefile))
Function:
The addresses of any global procedures in
segment are entered in the global vector.
Unless the segment is already linked all
machine code hunks are relocated.
Remarks:
A newly linked procedure replaces any existing
procedure using the same global number. Thus
it is possible to redefine library procedures.
Portability:
This function is found on other BCPL implemen-
tations. However, the relocation of machine
code is specific to this implementation.
121
GLOBUNIN
Purpose:
To unlink a code segment.
Example:
next.segment := GLOBUNIN( segment)
Function:
Global links to the segment which were set by
GLOBIN are cleared. All machine code hunks
are unrelocated.
Remarks:
GLOBUNIN does not affect any links to the
segment which have been made by the program.
Thus it cannot, by itself, ensure that the
segment can be unloaded safely. Leaving
links to an unloaded segment allows a class of
error which is intermittent and difficult to
find.
122
GLOBUNIN does not restore the previous setting
of a global. Thus if a segment redefines a
procedure in the program or library it may be
necessary to replace the earlier definition.
If for example the file ‘newwritef’ redefined
WRITEF, the following sequence might be used:
saved.writef := WRITEF
segment := LOADSEG( "newwritef")
GLOBIN( segment)
WRITEF := saved.writef
GLOBUNIN( segment)
Portability:
Available on some other BCPL implementations.
However, the handling of machine code is
specific to this implementation.
INPUT
Purpose:
To obtain the identity of the current input
stream.
Example:
stream := INPUT()
Remarks:
If there is no current input stream INPUT
returns ERRORSTREAM. Any attempt to read from
ERRORSTREAM causes an ABORT.
Portability:
Standard BCPL procedure.
123
LEVEL
Purpose:
To obtain a pointer to the current stack pos-
ition for possible use by LONGJUMP.
Example:
stackpointer := LEVEL()
Portability:
Standard BCPL procedure.
LOADSEG
Purpose:
To bring a CINTCODE file into store (or, if it
is already in store, to re-arrange it if
necessary) so that it can be linked (by
GLOBIN) into the global vector and executed.
Examples:
(1) segment := LOADSEG( string)
(2) is.successful := GLOBIN( LOADSEG( string))
(3) segment := LOADSEG( "/F.myfile")
Function:
String is interpreted as a filename in the
normal way. Thus "/S.myfile" refers to a
store file, "/F.myfile" to a current filing
system file and "myfile" to a store file if
there is one else a current filing system
file.
124
The specified file is accessed. If it is
found and is not in store then it is copied to
store. (The store file created is given the
name string with any device specifier omitted.
Thus
LOADSEG("/F.myfile")
and
LOADSEG("myfile")
Remarks:
As shown in example (2) GLOBIN can accept the
result of LOADSEG. If LOADSEG returns zero,
GLOBIN returns FALSE but in this case it does
not alter RESULT2 so that the cause of the
load failure can still be determined.
Portability:
LOADSEG is found in other BCPL implemen-
tations.
125
LONGJUMP
Purpose:
To cause a jump to a higher level procedure,
typically after an error or exception con-
dition.
Example:
LONGJUMP( stackpointer, label)
Function:
The new stackpointer is established and pro-
cessing continues from the specified label.
Remarks:
Since a label can only be addressed from with-
in the same procedure it is common to place
both the stackpointer and the label to be used
in globals. For example:
ljstackpointer := LEVEL()
ljlabel := errorlabel
. . .
. . .
Portability:
Standard BCPL procedure.
126
MAXVEC
Purpose:
To discover the size of the largest vector
obtainable by GETVEC without GETVEC having to
SHUFFLE.
Examples:
(1) max.free.vector := MAXVEC()
(2) UNLESS MAXVEC() = 0 DO
vector := GETVEC( MAXVEC())
Remarks:
To find the largest vector obtainable without
deleting unprotected files precede the call of
MAXVEC by SHUFFLE(FALSE).
Portability:
Part of extension A7 to the standard language.
127
MODE
Purpose:
To select the display mode.
Example:
is.successful := MODE( 5)
Function:
The bottom of screen memory for the new mode
is found and the heap adjusted if possible to
end just below this point. If the heap cannot
be adjusted (because areas that would become
part of the screen memory are in use) the
result is FALSE and RESULT2 is set to 15. If
the heap is adjusted then the new display mode
is selected and the result is TRUE.
Remarks:
If the BCPL system is running in the 2nd 6502
processor (using the Tube) then no adjustment
of the heap is necessary.
Portability:
Specific to this implementation.
128
MOVE
Purpose:
To provide a rapid transfer of a block of
words from one store location to another, or
to initialise store.
Example:
MOVE( from, to, words)
Remarks:
The move starts with the first word in the
block, and the two blocks can overlap. Thus
MOVE can be used to initialise a buffer as
follows:
Portability:
Specific to this implementation.
129
MOVEBYTE
Purpose:
To provide a rapid transfer of a block of
bytes from one store location to another.
Example:
MOVEBYTE( frombyte, tobyte, bytes)
Remarks:
The move starts with the first byte in the
block. If the two blocks overlap then
MOVEBYTE should be used for moving down in
store and BACKMVBY for moving up in store.
MOVEBYTE can be used to initialise a string in
a similar way to MOVE.
Portability:
Specific to this implementation.
MULDIV
Purpose:
To allow scaled or multiple length arithmetic.
Example:
result := MULDIV( a, b, c)
Function:
MULDIV calculates (a*b)/c, holding the
intermediate product (a*b) as a double length
integer. The remainder from the division is
left in global variable RESULT2.
130
Remarks:
If the result does not fit in a normal integer
the results returned by MULDIV are not de-
fined.
Portability:
Extension A8 of the standard language.
NEWLINE
Purpose:
To start a new line in the current output
stream.
Example:
NEWLINE()
Remarks:
In this implementation it places a line feed
character (0A hex) followed by a carriage
return character (0D hex) in the output
stream.
Portability:
A standard BCPL procedure.
NEWPAGE
Purpose:
To start a new page in the current output
stream.
Example:
NEWPAGE()
Remarks:
A form feed character (0C hex) is placed in
the current output stream.
Portability:
A standard BCPL procedure.
131
OPSYS
Purpose:
To give access to operating system services.
Examples:
value := OPSYS( functionnumber, x, y)
OPSYS( 8, 4) // set TX baud rate to 1200
Function:
In this implementation the function calls the
operating system procedure OSBYTE. The
functionnumber is placed in register A, x in
register X, and y in register Y. The return
is obtained from registers Y and X with X
holding the least significant byte. The
global MCRESULT contains the flags in the most
significant byte and register A in the least
significant byte.
Remarks:
Calls to other operating system entry points
such as OSASCI should use the procedure
CALLBYTE.
Portability:
Part of standard language extension Al2.
However the direct use of the operating system
in this way reduces portability to other
operating systems.
See also:
BBC Microcomputer User Guide.
132
OUTPUT
Purpose:
To obtain the identity of the current output
stream.
Example:
stream := OUTPUT()
Remarks:
If there is no current output stream OUTPUT
returns ERRORSTREAM. Any attempt to write to
ERRORSTREAM causes an ABORT.
Portability:
Standard BCPL procedure.
PACKSTRING
Purpose:
To convert a vector of characters into a
string.
Example:
string.words := PACKSTRING( fromunpacked,
tostring)
Function:
The length (n) of the string is given by
fromunpacked!0. The characters stored in
fromunpacked!1 to fromunpacked!n are placed in
tostring%1 to tostring%n and the length n is
placed in tostring%0. The result is the size
of tostring in words decreased by one. Thus
a one word string returns zero.
133
Remarks:
PACKSTR1NG is primarily intended for use in
converting existing BCPL programs. The
availability of the % operator makes the use
of vectors for characters unnecessary.
PACKSTRING is therefore provided in source
form in OPT and does not have an address in
the standard header files LIBHDR and SYSHDR.
Portability:
Standard BCPL procedure.
PUTBYTE
Purpose:
To place a byte in a string.
Example:
PUTBYTE( string, byteposition, byte)
Remarks:
Since the introduction of the % operator the
function of PUTBYTE is better provided by:
string%byteposition := byte
Portability:
Standard BCPL procedure.
134
RANDOM
Purpose:
To generate a series of random numbers.
Example:
randominteger := RANDOM( randominteger)
Function:
The result is obtained from the given par-
ameter by an algorithm which generates an
approximately random sequence of numbers,
which repeats only after every possible number
(both positive and negative) has been
generated.
Remarks:
If a series of calls to RANDOM is always
started with the same seed number, they will
generate the same sequence of ‘random’ num-
bers. This may be useful in testing alter-
native strategies with random data. If only
a few bits of random data are required, it is
best to use the more significant part of the
number, since, for example, the least sig-
nificant bit is odd and even alternately. A
random starting number can usually be obtained
by a measure of the time between console key
depressions. This requires a point in the
program at which it is known that all operator
input has been read, and that further oper-
ator input is awaited. The seed number is
then obtained by:
Portability:
Similar procedures are provided on many
implementations.
135
RDARGS
Purpose:
To perform an initial analysis and verifi-
cation of the arguments for a utility.
Examples:
(1) endofargs := RDARGS( keys, argumentvector,
size)
(2) RDARGS( "FROM/A,TO,CHECKING/S", argv, 100)
(3) RDARGS( "FROM,,,TO=AS", argv, size)
Function:
One line of input is read and analysed for
conformity with the specified keys. The
individual arguments in the line are separated
and placed in argumentvector, provided that
the space taken in the vector does not exceed
size. Size is the size of argumentvector in
words (i.e. the GETVEC or VEC parameter).
Keys
136
The input
FROM a TO b
a b
CHECKING a
FROM a b AS z
TO z FROM a b c
TO=z FROM=a
TO z FROM "FROM"
a b c z
b FROM a
137
The argument vector
The result
Remarks:
RDARGS is effective in analysing the arguments
given but it does not convert any arguments to
an internal form such as a number. Such
conversions are not difficult in BCPL but the
variety of requirements makes this stage of
validation appropriate to individual programs.
Portability:
This procedure is provided on other BCPL im-
plementations.
138
RDBIN
Purpose:
To read binary data from an input stream.
Example:
bincharacter := RDBIN()
Function:
The procedure returns the next character from
the current input stream, unless the input
stream is exhausted when it returns
ENDSTREAMCH.
Portability:
Part of extension A10b) of the standard lan-
guage.
RDCH
Purpose:
To read a character from the input stream.
Example:
character := RDCH()
Function:
The next character from the current input
stream is returned. The carriage return line
feed pair are converted to the single charac-
ter ‘*N’. (Specifically CR is treated as
‘*N’ and LF is ignored). The end of stream
is indicated by ENDSTREAMCH. The character
135 is also treated as ENDSTREAMCH. This
character may be obtained from the keyboard by
disabling cursor editing (*FX 4,1) and press-
ing COPY. Cursor editing may be re-enabled by
*FX 4,0.
139
Only the bottom seven bits of the character
are returned. Thus RDCH can be used on input
streams which use bit 7 for parity or other
purposes (but note that character 135, which
has bit 7 set, is treated as ENDSTREAMCH).
Portability:
Standard BCPL procedure.
RDITEM
Purpose:
To read the next string from the current input
stream.
Example:
itemtype := RDITEM( tovector, maximumsize)
Function:
The next argument or tag in the input stream
is placed as a string in tovector, of size
maximumsize words. The itemtypes returned
are:
Remarks:
Leading spaces are suppressed.
Unquoted items
140
Quoted items
Portability:
Similar procedures are available in other BCPL
implementations.
READ
Purpose:
To read a file from the current filing system
into store or to copy a store file to another
store file or to make a store file contiguous.
Examples:
(1) is.successful := READ( fromfile, tofile,
contiguous)
(2) READ( "myfile", 0, TRUE)
(3) is.successful := READ( "/F.myfile", "xxx",
FALSE)
(4) is.contig := READ( "sfile", "sfile", TRUE)
(5) READ( "file1", "file2", FALSE)
(6) READ( "/S.xxx", 0, FALSE)
(7) READ( "file1", "/F.file", FALSE)
141
Function:
There are two main functions of this routine:
142
Contiguous is TRUE if the store file created
must be a contiguous file, FALSE if it need
not be contiguous.
143
This is demonstrated by example (4). Assuming
that the store file ‘sfile’ exists it makes
the file contiguous, doing nothing if the file
is already contiguous. If contiguous were
FALSE in this example then the procedure would
only make the file contiguous if there was
room but would return TRUE in any case. If
‘sfile’ did not exist in store then the effect
would be to copy ‘sfile’ from the current
filing system to store.
Remarks:
When copying a file from the current filing
system into store the operating system OSFILE
routine is used if possible (i.e. if the size
of the file can be obtained without reading
the file and if a sufficiently large vector
can be obtained to read it into). Use of
this routine results in a faster copy than any
other method.
144
- if reading from a filing system which
enables the file length to be found (e.g.
disk, Econet), it guarantees that the fast
OSFILE routine will be used.
Portability:
Specific to this implementation.
READN
Purpose:
To read a decimal integer from the current
input stream.
Example:
integer := READN()
Remarks:
Initial spaces, tabs or newlines are ignored.
An initial sign is optional. The integer is
terminated by the first non-decimal character.
If the integer is greater than the maximum or
less than the minimum value that can be held
in one word the result is undefined.
Portability:
Standard BCPL procedure.
145
READVEC
Purpose:
To read a file into a given vector.
Examples:
(1) is.successful := READVEC( fromfile, tovec,
vecsize)
(2) v := GETVEC(20)
is.successful := READVEC( "myfile", v, 20)
Function:
Fromfile is interpreted in the normal way.
Thus "/S.myfile" refers to a store file,
"/F.myfile" to a current filing system file
and "myfile" to a store file if there is one
else a current filing system file. The only
devices allowed are store and the current
filing system - thus specifying fromfile as
"/P", for example, would be an error.
Remarks:
If the result is FALSE then the contents of
tovec are undefined. In particular the byte
count in word 1 will not have been set up.
Depending on the circumstances the original
contents of the vector may or may not have
been changed.
146
If the file is too big to fit in tovec RESULT2
is set to 51.
LET V = VEC 30
READVEC( "file", V+9, 21)
Portability:
Specific to this implementation.
READWORDS
Purpose:
To read a number of words of data from the
input stream.
Example:
wordsread := READWORDS( destination, words)
Function:
Binary data is read from the current input
stream until either the specified words have
been read or the stream is exhausted. The
result is the actual number of words read.
Remarks:
Using READWORDS is more efficient than
repeated use of RDBIN. This is particularly
so when reading from a filing system that
supports the operating system OSGBPB routine
(read/write block of bytes).
147
The use of READWORDS may be combined with the
use of RDBIN and RDCH, but a call to UNRDCH
immediately following a call to READWORDS may
not work.
Portability:
The procedure is provided on some other BCPL
implementations.
RENAME
Purpose:
To rename a file on the current filing system
or in store.
Examples:
RENAME( fromfilename, tofilename)
is.successful := RENAME( "tempfile", "final")
RENAME( "/F.file1", "file2")
Function:
If the file fromfilename can be found, it is
renamed to tofilename. The result is TRUE if
successful, FALSE if not. In the latter case
RESULT2 contains the error code.
148
Remarks:
For store files, if a file called tofilename
already exists the rename fails but a file
that is open or linked may be renamed.
Portability:
Similar procedures are provided on other
implementations.
RESUMECO
Purpose:
To transfer control to another coroutine at
the same level.
Example:
reply := RESUMECO( coroutine, parameter)
Function:
If the second coroutine exists and is in a
waiting state, it resumes processing and
receives the parameter. The parent co-
routine of the new coroutine becomes the
parent of the transferring coroutine.
149
Remarks:
If the second coroutine is not in a suitable
state RESUMECO calls ABORT.
Portability:
Part of the published method of implementing
coroutines in BCPL.
RUNPROG
Purpose:
To enable a program to run another program or
utility or to issue a ‘*’ command to the
operating system.
Examples:
(1) result :=
RUNPROG( writefstring, p1, p2, p3, p4)
(2) res := RUNPROG( "TYPE %S", textfile)
(3) RUNPROG( "**TAPE") // select tape filing
// system (** must be
// used for asterisk
// in strings)
Function:
A temporary file is created using the param-
eters as parameters of a call of WRITEF (but
note that only 4 parameters apart from the
WRITEF string are allowed). The file is ter-
minated with LF/CR.
150
If this results in a program being run the
program is loaded and is entered (by calling
START) with the temporary file as its input
stream (the next character read will be that
following the program name) and the console as
its output stream.
Remarks:
The procedure ERRORMSG may be useful for
printing an error message if the call to
RUNPROG fails.
Portability:
Developed for this implementation.
151
SAVE
Purpose:
To copy a store file. A special option is
provided for copying a store file to a current
filing system file with the same name.
Examples:
(1) is.successful := SAVE( fromfile, tofile)
(2) SAVE( "myfile", 0)
(3) is.ok := SAVE ("file1", "/F.file2")
(4) SAVE( "file1", "file1")
(5) SAVE( "/F.file", "/P")
(6) SAVE( "file1", "file2")
Function:
The store file fromfile is copied either to
the file specified by tofile or, if tofile is
0, to a file named fromfile in the current
filing system. The result is TRUE if the copy
succeeds, FALSE if it fails. In the latter
case RESULT2 contains the error code.
152
Remarks:
Making fromfile contiguous (if possible) may
involve calling SHUFFLE and hence deleting
unprotected store files.
Portability:
Specific to this implementation.
153
SAVEVEC
Purpose:
To write the contents of a vector as a file.
Examples:
(1) is.successful := SAVEVEC( fromvec, tofile)
(2) LET v = VEC 10
MOVE( data, v+2, 9)
v!1 := 17 // 17 bytes of data
SAVEVEC( v, "/F.myfile")
(3) SAVEVEC( myvec, "/P")
Function:
The data in fromvec is written to the file
tofile. If the file already exists it is
overwritten. The result is TRUE for success,
FALSE for failure. In the latter case RESULT2
contains the error code.
Remarks:
Fromvec need not be a heap vector. It may be
any data area, provided that it is set up in
the correct format.
154
If tofile is a store file and there is not
enough room in store for it then no file is
created and RESULT2 is set to 51 (note that if
stream I/O is used to write to a store file
then the file is truncated if there is not
enough room).
Portability:
Specific to this implementation.
SELECTINPUT
Purpose:
To select the current input stream.
Examples:
SELECTINPUT( stream)
SELECTINPUT( FINDINPUT( "/C"))
Function:
If stream is an identifier, which has been
returned by FINDINPUT or FINDXINPUT, the
stream is selected for input.
Remarks:
It is possible to reselect the current stream.
SELECTINPUT( 0) is allowed, and causes selec-
tion of the ERRORSTREAM, in which case any
read operation will cause an ABORT. If
stream is not a valid input stream then ABORT
is called.
Portability:
Standard BCPL procedure.
155
SELECTOUTPUT
Purpose:
To select the current output stream.
Examples:
SELECTOUTPUT( stream)
SELECTOUTPUT( FINDOUTPUT( "/C"))
Function:
If stream is an identifier, which has been
returned by FINDOUTPUT or FINDXOUTPUT, the
stream is selected for output.
Remarks:
It is possible to reselect the current stream.
SELECTOUTPUT( 0) is allowed, and causes selec-
tion of the ERRORSTREAM, in which case any
write operation will cause an ABORT. If
stream is not a valid output stream then ABORT
is called.
Portability:
Standard BCPL procedure.
156
SHUFFLE
Purpose:
To rearrange the store files so as to maximise
the contiguous free heap space.
Examples:
SHUFFLE(TRUE)
SHUFFLE(FALSE)
Function:
If the parameter is TRUE all unprotected store
files are deleted.
(2) i f t h e a l l o c a t e d a r e a a b o v e t h i s i s
movable (i.e. if it is part of an unlinked
file) then it is moved down into the unal-
located area. There is now an unallocated
area immediately above the area that has
been moved down and the process is re-
peated for this area;
157
(4) if nothing could be moved to the unal-
located area, or the area was completely
filled, then the process is repeated for
the next unallocated area (working up the
heap). If the unallocated area was not
completely filled the process is repeated
for the remaining unallocated part of this
area.
Remarks:
The procedure MAXVEC may be used to find the
size of the largest contiguous free area.
Portability:
Specific to this implementation.
SOUND
Purpose:
To generate a sound.
Example:
LET stab = TABLE 1, −15, 53, 20
SOUND( stab)
Function:
The parameter is a four-word table or vector
containing the four parameters defining a
sound. The table is passed to the operating
system using the OSWORD call. Details of the
sound parameters are given in the BBC Micro-
computer User Guide.
158
Remarks:
This procedure is provided mainly for ease in
converting BASIC programs to BCPL. In many
cases it will be easier to make the OSWORD
call directly using CALLBYTE.
Portability:
Specific to this implementation.
SPLIT
Purpose:
To split off a tag or prefix from a string for
separate processing.
Examples:
endptr := SPLIT( prefix,char,string,
startptr)
endptr := SPLIT( device, '.', name, 0)
Function:
The parameters are:
159
Remarks:
SPLIT can be used to extract successive ar-
guments from a string, provided all arguments
are separated by the same character. The
last argument will return zero. If the
string in prefix would exceed 30 characters,
it is truncated to 30 characters.
Portability:
While procedures similar to SPLIT are provided
in several implementations, there are differ-
ences which reduce portability.
STACKSIZE
Purpose:
To determine the free space in the current
stack.
Example:
stack.size.left := STACKSIZE()
Remarks:
One reason for STACKSIZE is to permit the
vector requested by APTOVEC to be adjusted to
the available space.
Portability:
Part of extension A7 of standard BCPL.
160
START
Purpose:
To provide a standard start point for any
program.
Examples:
LET START() BE ...
START( parameter)
Function:
Every program must include a START procedure,
and START is the entry point to that program.
Returning from the START procedure is one way
of ending a program.
Remarks:
In this implementation the parameter is always
zero when START is called by the BCPL system.
START is entered with the console or other
command line source selected for input and the
console selected for output. Reading the
input stream will obtain any text in the
command line after the command that loaded the
program. If the program is entered from the
console, reading after the carriage return
will obtain input from the console. If the
program is entered using a command file (or by
the procedure RUNPROG), subsequent input will
be obtained from the command file (or tem-
porary RUNPROG file).
Portability:
START is a standard procedure, but different
implementations have different ways of passing
the input parameters to the procedure.
161
STARTINIT
Purpose:
To enable a program to control its environ-
ment.
Example:
LET STARTINIT() = 3000 // sets stack size
Function:
If STARTINIT is defined, it is called during
the initialisation of a program. STARTINIT
must return the stack size required by the
program.
Remarks:
STARTINIT is called in a privileged state and
can alter a number of features of its environ-
ment.
162
Portability:
Specific to this implementation.
STOP
Purpose:
To end a program.
Examples:
STOP( 0)
STOP( returncode)
Function:
A call to STOP indicates a controlled com-
pletion of a program. The result is normally
a return to the command state. By convention
a zero return code indicates successful com-
pletion, a positive code is a fatal error and
a negative code is a warning or comment.
Codes below −100, between 501 and 999 and
above 1256 are available for applications use.
Remarks:
Normally any non-zero returncode is displayed
by calling procedure ERRORMSG.
Portability:
A standard BCPL function. A returncode of 0
for success is also standard. The use of
other returncodes is implementation dependent.
163
TESTFLAGS
Purpose:
To test if there is more input to read.
Examples:
flag.was.set := TESTFLAGS( flagmask)
IF TESTFLAGS( CONSOLE.KEY) THEN
WHILE TESTFLAGS( MORE.INPUT) DO
Function:
One or more flags, selected by the parameter
flagmask, are tested. The result is TRUE if
any of the tested flags were set, and the
state of all tested flags is placed in
RESULT2.
CONSOLE.KEY
tests if there are more characters in
the operating system’s console input
buffer.
MORE.INPUT
tests if more input can be read from
the current input stream without
further calls to the operating system.
This test is only useful on a console
stream, (device /C).
Remarks:
The test for CONSOLE.KEY is normally used to
permit a process to be interrupted by any
console key depression. The console can be
read in two ways.
164
When the console is being read character by
character as device /K the test indicates that
another character can be read without pausing
for operator input.
Portability:
The procedure is used in other BCPL implemen-
tations, but the meaning of the testflag bits
is not fixed. TESTFLAGS(1) is often used to
decide to terminate a process in response to
some operator input. This can carry over
unchanged to this implementation, since
CONSOLE.KEY is 1.
165
TESTSTR
Purpose:
To test the characteristics of the current
input and output streams.
Examples:
is.streamtype := TESTSTR( streamtype)
UNLESS TESTSTR( STYPE.INT) DO
Function:
One or more flags, selected by the parameter
streamtype, are tested. The result is TRUE
if any of the tested flags is set, and the
state of all tested flags is placed in
RESULT2.
STYPE.TERM
tests if the device is a ter-
minal on which the result, after out-
putting text not terminated by ‘*N’,
will be a part line of text permit-
ting input on the same line.
STYPE.INT
tests if the device is interactive and
so can respond to prompts from the
program.
Remarks:
These tests permit a program to be written to
provide a helpful interaction with the oper-
ator, while adapting correctly if it receives
its input parameters from a command file or
other non-interactive device (but the system
cannot detect whether ‘console’ input is
coming from the console or from a *EXEC file).
166
See also the section ‘File and stream
handling’ in chapter 8.
Portability:
Similar features are provided in some other
implementations.
TIME
Purpose:
To read the 15 least significant bits of the
elapsed-time clock.
Example:
clock.time := TIME()
Function:
The bottom 15 bits of the elapsed-time clock
are read. Since each tick is 10ms the result-
ing time wraps round approximately every five
and a half minutes (327.68 seconds).
Remarks:
The manifest TICKSPERSEC declared in LIBHDR
may be used to convert time intervals into
seconds.
167
Suitable code to adjust for wraparound might
be:
t1 := time()
. . . // code to be timed
interval := time() - t1
if interval < 0 then
interval := interval + #X8000
Portability:
Part of extension A14 of the BCPL language.
TRAP
Purpose:
To cause a trap to the command state.
Example:
TRAP( traptype, letter)
Function:
The procedure causes a trap with the given
traptype and letter. All values of traptype
below 10 are reserved for system use.
Application programs may use other values as
required.
Trap 35 Y
168
Remarks:
This procedure may be useful when developing
programs - for example a call of TRAP may be
included so that the program breaks out to the
console when some specific condition occurs.
In most cases the normal DEBUG facilities will
be sufficient, however.
−2 Fatal error;
−1 Abort;
0 End of program;
2 Break point reached (DEBUG);
3 Requested trap (DEBUG);
4 ESCAPE;
5 GETVEC failure;
6 PAUSE.
Portability:
Specific to this implementation.
UNLOADSEG
Purpose:
In some systems to return to free store the
space used by a loaded segment.
Example:
UNLOADSEG( segment)
169
Function:
In this system UNLOADSEG is a dummy procedure
which returns 0. It is provided for compat-
ibility with systems where it must be called
after calling GLOBUNIN to release the space
occupied by the segment.
Remarks:
UNLOADSEG is declared in SYSHDR.
Portability:
UNLOADSEG is provided by other BCPL implemen-
tations.
UNPACKSTRING
Purpose:
To separate the bytes of a string into separ-
ate words.
Example:
UNPACKSTRING( fromstring, tounpacked)
Function:
The length of the string is placed in
tounpacked!0 and the characters are placed in
order starting at tounpacked!1.
Remarks:
See PACKSTRING.
Portability:
Standard BCPL procedure.
170
UNRDCH
Purpose:
To step back the current input stream, so that
the next byte read is the same as the last.
This permits a separate part of the program to
read the last character read. For example a
procedure reading a number must often find the
terminator before it can return the number.
However, another procedure often needs to ex-
amine the terminator, so the first procedure
normally ends with a call of UNRDCH.
Example:
UNRDCH()
Remarks:
UNRDCH should not be called more than once
between successive read commands on the input
stream. The effect of a second call is un-
defined, as is the effect of a call on a newly
opened stream.
Portability:
Standard BCPL procedure.
VDU
Purpose:
To write a number of bytes to the VDU driver.
Examples:
(1) VDU( string, p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10)
(2) VDU( "28, 0, 5, 39, 0")
(3) VDU( "31, %, %", x, y)
(4) VDU( "24,%;%;%;%;", left, bottom,
right, top)
(5) VDU( "23,&FD,8,#X1C,28,107,127,107,0;")
171
Function:
String is treated as a list of numbers or ‘%’
signs. Items in the list are separated by ‘,’
or ‘;’ and may be preceded or followed by any
number of spaces. Numbers are normally deci-
mal (e.g. 123) but are treated as hexadecimal
if prefixed by ‘&’ or ‘#X’ (e.g. &1F, &1f,
#X1f, #x1F).
Remarks:
This procedure is designed to make conversion
of BASIC programs to BCPL very simple since
the format of string corresponds to the format
of the BASIC command VDU. It is also very
useful in writing BCPL programs that use any
VDU driver facilities. For instance, example
(3) could form the body of a procedure to set
the text cursor to position (x, y) and example
(4) could be used for defining a graphics
window.
172
Calling VDU is equivalent to making a series
of calls to WRBIN, but is much faster and in
many cases is far more convenient.
Portability:
Specific to this implementation.
VDUINFO
Purpose:
To give the numbers of rows and columns
available with the current display mode.
Examples:
No.of.rows := VDUINFO(1)
No.of.cols := VDUINFO(2)
Function:
The result is the number of rows or columns of
text that can be displayed with the current
display mode (e.g. in mode 7 VDUINFO(1) re-
turns 25 and VDUINFO(2) returns 40).
Remarks:
This procedure may be useful in writing
programs that adapt their output according to
the current display mode.
Portability:
Specific to this application.
173
VECTOFILE
Purpose:
To convert a vector into a file.
Examples:
(1) is.successful := VECTOFILE( fromvec,
tofile)
(2) LET v = GETVEC(20)
MOVE( data, v+2, 19)
v!1 := 38 // no. of bytes of data
VECTOFILE( v, "/F.myfile")
Function:
Fromvec must be a heap vector (i.e. one
obtained by a call of GETVEC) set up as
follows :
Remarks:
If fromvec is not a heap vector or if the
byte count in fromvec!1 is invalid ABORT is
called.
174
If tofile is a store file then the vector
becomes the file. If it is not a store file
then the vector is returned to the heap after
copying the data.
Portability:
Specific to this implementation.
WRBIN
Purpose:
To write a binary byte.
Example:
WRBIN( binarycharacter)
Remarks:
The binarycharacter is added to the output
stream, without any checks on its content.
Portability:
Part of extension Al0b) of the standard lan-
guage.
175
WRCH
Purpose:
To write a character to the output stream.
Example:
WRCH( character)
Function:
If the character is ‘*N’, it is expanded to
line feed and carriage return.
Portability:
Standard BCPL procedure.
WRITEA
Purpose:
To output a word address.
Example:
WRITEA( wordaddress)
Function:
If the wordaddress is that of a named pro-
cedure, the first seven characters of the name
are written to the current output stream,
following an initial space. Otherwise the
wordaddress is output. In both cases the
field width is 8 characters.
Remarks:
This procedure is used by the debugging facil-
ities, and is expected to be of use to special
debugging features.
Portability:
Developed for this implementation.
176
WRITEBA
Purpose:
To output a byte address.
Example:
WRITEBA( byteaddress)
Function:
All addresses in the debug package are given
in 16 bit word format, and odd byte addresses
are shown as the equivalent 16 bit word
address, followed by an ‘H’ - corresponding to
the high byte.
Remarks:
See WRITEA remarks.
Portability:
Developed for this implementation.
WRITED
Purpose:
To write an integer in a given field width.
Example:
WRITED( integer, fieldwidth)
Remarks:
Integer is treated as a number in the range
minus 32767 to 32767. It is output at the
right of the field. If the fieldwidth is not
sufficient the integer is output in the mini-
mum fieldwidth necessary.
177
Portability:
Standard BCPL procedure.
WRITEDB
Purpose:
To output a double length integer.
Example:
WRITEDB( doubleinteger)
Function:
The doubleinteger is written to the current
output stream, with a fieldsize of 8 charac-
ters. Doubleinteger must be a 2 word vector
and doubleinteger!0 contains the least sig-
nificant 4 decimal digits in binary, modulo
10000, while doubleinteger!1 contains the most
significant 4 digits in binary.
Remarks:
The double length integer format is restricted
to positive integers. This format is used in
the internal count of jumps/procedure calls
used in DEBUG.
Portability:
Developed for this implementation.
178
WRITEF
Purpose:
To write one or more arguments in a specified
format.
Examples:
WRITEF( format,a,b,c,d,e,f,g,h,i,j,k)
WRITEF( "%S is aged %N*N", name, age)
WRITEF( format, argument1, argument2)
Function:
The string format is written to the current
output stream. Each ‘%’ causes the next
argument to be converted and output according
to the format character following the ‘%’, as
follows:
Portability:
WRITEF is a standard BCPL procedure. However
this implementation provides more conversions
than the standard procedure (but does not
provide %O to output in octal). Some of
these conversions are available on some other
implementations.
179
WRITEHEX
Purpose:
To write a hexadecimal number in a given field
width.
Example:
WRITEHEX( integer, fieldwidth)
Function:
A hexadecimal representation of the integer is
written to the current output stream in the
given fieldwidth. Leading zeroes are shown.
If the fieldwidth is too small for the in-
teger, only the least significant hexadecimal
digits are output.
Portability:
Standard BCPL procedure.
WRITEN
Purpose:
To write an integer in the minimum field width
Example:
WRITEN( integer)
Portability:
Standard BCPL procedure.
180
WRITEOCT
Purpose:
To write an octal number in a given field
width.
Example:
WRITEOCT( integer, fieldwidth)
Function:
An octal representation of the integer is
written to the current output stream in the
given fieldwidth. Leading zeroes are shown.
If the fieldwidth is too small for the
integer, only the least significant octal
digits are output.
Remarks:
WRITEOCT is declared in SYSHDR and included in
section "WRITEOC" of the CINTCODE library file
LIB.
Portability:
Standard BCPL procedure.
WRITES
Purpose:
To write a string.
Examples:
WRITES( string)
WRITES( "*NThis text is output")
Function:
The fieldwidth is the length of the string.
Portability:
Standard BCPL procedure.
181
WRITET
Purpose:
To write a string in a specified field width.
Examples:
WRITET( string, fieldwidth)
WRITET( "This is output in 30 chars", 30)
Function:
Trailing spaces are added if necessary to make
the string fit the field width. If the text
is too long to fit, the minimum field width to
hold the text is used.
Remarks:
WRITET is declared in SYSHDR and included in
section "WRITET" of the CINTCODE library file
LIB.
Portability:
This procedure is found in other BCPL
implementations.
WRITEU
Purpose:
To write an unsigned integer in a given field
width.
Example:
WRITEU( unsignedinteger, fieldwidth)
Function:
The unsignedinteger is treated as a number
between 0 and 65,535. If the fieldwidth is
not sufficient for all significant digits, the
unsignedinteger is output in the minimum
necessary field width. Leading zeroes are
printed as spaces.
182
Remarks:
WRITEU is declared in SYSHDR and included in
section "WRITEU" of the CINTCODE library LIB.
Portability:
This procedure is found in other BCPL
implementations.
WRITEWORDS
Purpose:
To write a number of words of data to the
current output stream.
Example:
WRITEWORDS( source, words)
Function:
The specified number of words of binary data
are written to the current output stream.
Remarks:
This procedure gives a more efficient transfer
of data than repeated calls to WRBIN. This is
particularly so when writing to a filing sys-
tem which supports the operating system OSGBPB
(read/write block of bytes) routine.
Portability:
The procedure is provided on some other BCPL
implementations.
183
184
6 Run Time
This chapter provides background information on
the BCPL CINTCODE system. An understanding of
the features described is not necessary for many
users of the system. However, experienced pro-
grammers should find the contents of this chapter
help them in making full use of the system.
Further details of some of the topics discussed
are given in the Appendix.
Command files
GETVEC
Layout of store
RUNPROG
Stacks
Store files
Streams
185
COMMAND FILES
EX exfile parameters
186
Programs run from command files
UNRDCH()
CH := RDCH() REPEATUNTIL CH='*N' |
CH=ENDSTREAMCH
187
The section ‘File and stream handling’ in chapter
8 explains how a program can tell whether it is
reading from the console or from a file.
188
FAULT, EVENT AND ESCAPE HANDLING
Faults
Events
189
ESCAPE
190
Note that if ESCAPE is pressed while the system is
executing machine code called from BCPL then the
BCPL system can take no action until control is
passed back to it.
191
A program may choose for the BCPL system to react
to ESCAPE as if it were in the command state
rather than the run state. In particular this
means that the program will never trap to the
command state with the ‘Interrupted’ message.
Reasons for doing so might be:
SYSINDEX!I.RSTATE!R.MCST :=
SYSINDEX!I.RSTATE!R.MCST & NOT M.TRAPESC
SYSINDEX!I.CSTATE!R.MCST :=
SYSINDEX!I.CSTATE!R.MCST & NOT M.TRAPESC
192
To re-enable normal ESCAPE handling include the
line:
SYSINDEX!I.CSTATE!R.MCST :=
SYSINDEX!I.CSTATE!R.MCST | M.TRAPESC
GETVEC
193
Certain programs may prefer to have GETVEC return
a failure indication than to trap to the command
state. For example the program may be designed to
be operated by someone who would not know how to
react to the ‘store needed’ message.
SYSINDEX!I.RSTATE!R.MCST :=
SYSINDEX!I.RSTATE!R.MCST & NOT M.TRAPGV
SYSINDEX!I.CSTATE!R.MCST :=
SYSINDEX!I.CSTATE!R.MCST & NOT M.TRAPGV
SYSINDEX!I.CSTATE!R.MCST :=
SYSINDEX!I.CSTATE!R.MCST | M.TRAPGV
194
LAYOUT OF STORE
Zero page:
A 256 byte area used by the operating system
and the BCPL Language ROM. Bytes 112 to 143
are available for use by applications.
VDU buffer:
In display mode 7 this is a 1024 byte buffer.
In other display modes it is larger (see the
description of procedure MODE in chapter 5).
195
Top of RAM:
8192 words for Model A. 16384 words for
Model B.
Operating system:
The operating system ROM uses the addresses
from word 24576 to 32767.
196
Loading a file (or segment)
197
Linking to the global vector
198
Relevant built in commands
199
Since LOADSEG places the segment in free store, it
will fail to load if there is not enough room in
store, or even if the free store is fragmented so
that one section of the segment cannot fit. Thus
it may be necessary to provide some way of en-
suring the load will fit, either by reserving
sufficient space which is released before the
load, or by having a recovery strategy if the load
will not fit.
or
GLOBIN( firstsegmentloaded)
200
RUNPROG
201
Note that even if the specified file contains a
procedure STARTINIT it is not called and so the
program being run is entered with the same stack
and same options for handling ESCAPE and running
out of store as the program calling RUNPROG.
202
- The calling program must have a big enough
stack to cater for all the stack requirements
of the called program (plus an overhead of
about 30 words for the call of RUNPROG
itself).
STACKS
203
In this implementation the first few words in the
stack following the stack pointer position are:
204
The ability to run in the command state while
maintaining the current run state is used to pro-
vide the extensive debugging features described in
chapter 7. (Utilities such as DEBUG, HEAP etc.
run using the root stack.)
205
The procedure LONGJUMP provides a means of un-
winding a chain of procedure calls by returning
directly to a specified label and stack pointer
position. A label can only be addressed directly
if it is in the same procedure. Thus a label for
use by LONGJUMP is normally transferred to a glo-
bal or static variable. Similarly the procedure
to which LONGJUMP will jump normally initialises a
global or static variable with the stack pointer
(obtained by the procedure LEVEL).
Initialisation
206
Starting
207
Stopping
208
A fatal trap is an error discovered by the inter-
preter. It causes an entry to the command state
in the same way as ABORT, but it cannot be trapped
by the program. A fatal trap typically arises
from stack overflow or calling a non-existent
procedure.
*** ERROR: x
STORE FILES
209
All space used for store files is allocated from
the heap. Every store file has a ‘file control
block’ (FCB) and a ‘file name block’ (FNB). The
FCB contains pointers to the other blocks
associated with the file and links to other files.
The FNB just holds the file name. Unless the file
is a zero-length file it also has one or more data
blocks. These hold the contents of the file. The
formats of the various blocks are detailed in the
Appendix.
210
STREAMS
211
USE OF FILING SYSTEMS
!*DISK
RUNPROG( "**ROM")
212
The procedure FSTYPE (see chapter 5) provides the
information required. The standard version of
this procedure caters for the tape, ROM, disk and
Econet filing systems. If new filing systems are
added then users can replace the standard version
with a version of their own containing the charac-
teristics of the new filing system. It should be
stressed, however, that if they do not replace the
standard FSTYPE then BCPL will still work with the
new filing system, but certain operations may be
slower than they need be.
213
- Whether the filing system is the tape or the
ROM filing system. This information is used
to set up message and error recovery options
using the *FX 139 command before opening a
file. Specifically for the tape filing system
the commands:
214
7 Debugging Aids
This chapter describes the range of debugging aids
provided with the BCPL CINTCODE system. Exper-
ienced users should find the summary of the
debugging commands given in chapter 11 is a suf-
ficient reminder for most purposes.
215
DEBUG - program test utility
Introduction
Covers topics applying to all facilities.
Altering memory
Bases
How to work in decimal, octal, hexadecimal or
characters.
Breakpoints
Calculating
Counting
The facility to run to a known point.
Displays
Limits
Setting the range for traces or statistics
collection.
Memory search
Finding words or procedures in memory.
Overlays
How the debugging functions are brought into
store.
Statistics
How to collect information on program oper-
ation.
Traces
How to monitor the execution of a program at
the instruction, jump or procedure level.
216
Introduction
DEBUG is entered by
!DEBUG
217
Testing a program with DEBUG
!LINK filename
!INIT parameters
218
(7) If the program has not ended then there are
several options. The program can be run to
another breakpoint or count or DEBUG can be
exited. In this case testing can be abandoned
by:
!TIDY
!CONT
Commands
219
Numbers and addresses
*2000/2 = B
220
Thus
*T
*12T
traces 12 lines.
Globals
*G300 B2
*G400 + G401 =
221
Variables
*SV3 234
*V3 =
*V4 * 13 + G450 =
Altering memory
S address value
or
222
If only one value is specified then the word
specified by address is updated to that value. If
a list of values (separated by spaces) is speci-
fied then successive words, starting at address,
are updated to value1, value2 etc.
*S1234 367
*SG300 0 0
*SV4 1 2 3
S address
223
The available options at this stage are:
ESCAPE
Terminate the command and return to the ‘*’
prompt.
RETURN
Leave the contents of this address unchanged.
Display the next address and contents in a
similar way.
value RETURN
Update the contents of this address to value
and display the next address and contents in a
similar way.
*S5260<CR>
5260 (148C): 16965 4245 EB :123<CR>
5261 (148D): −12345 CFC7 GO :<CR>
5262 (148E): 0 0000 .. :#X56A2 26 26<CR>
5265 (1491): 2560 0A00 .* :<ESC>
*
224
The next two examples show how the command can be
used to alter globals and variables.
*SG353<CR>
G353 (0DE3): 4321 10E1 a. :0 −888<CR>
G355 (0DE5): −888 FC88 .| :<CR>
G356 (0DE6): 0 0000 .. :−888<CR>
G357 (0DE7): −1 FFFF .. :<ESC>
*
*SV3<CR>
V 3 (1FA9) 66 0042 B. :'A<CR>
V 4 (1FAA) 67 0043 C. :'B<CR>
V 5 (1FAB) 0 0000 .. :<ESC>
*
Bases
225
Once the format has been changed the new format is
used as the default until the format is changed
again.
Breakpoints
226
Running to a breakpoint
Calculating
+n Add n
-n Subtract n
*n Multiply by n
/n Divide by n
%n Obtain the remainder after dividing by n
< Shift left one bit
> Shift right one bit
&n Logical AND with n
|n Logical OR with n
! Obtain the contents of the address pointed to
by the current variable
. Equivalent to !
227
One line may contain several commands. If so they
are executed from left to right. The following
examples illustrate the use of several commands in
a line:
*1000 $O =
*9999 < $X =
*G444 + 5 ! =
Counting
228
The feature works by counting the number of
branches (including procedure calls and returns)
made by the program. Provided a program is run in
an identical environment with identical input then
the count is repeatable (i.e. it is always the
same at a given point in the program). Note that
slight differences in the heap can cause vari-
ations in the count (because GETVEC may have more,
or less, work to do) and therefore when running to
a known point the count may only be an approximate
guide (unless the system is rebooted before each
run and an identical sequence of operations
carried out).
229
(4) the program is continued again and runs norm-
ally.
Displays
*$X:20$C:20
Other displays
Limits
230
Limits can be set by the command ‘Ln’. This sets
the lower limit at the current variable and the
upper limit at n. If n is zero no upper limit is
set.
For example:
*G340L10000
*0L0
Memory search
231
MP myproc
Overlays
232
DEBUG loads and links the overlay required auto-
matically when a function it provides is reques-
ted. Only one of these overlays is linked at any
time, and the current overlay can be unlinked by
the command ‘W’. If the STATS overlay has col-
lected some statistics, these would be lost if the
overlay were deleted. To prevent accidental de-
letion, requests for functions in other overlays
are superseded until STATS is unlinked, typically
by the command ‘W’.
Statistics
233
Two levels of statistics collection are supported:
234
0T collects statistics until ESCAPE is pressed, a
breakpoint is reached, or the program ends.
Traces
235
Tracing only takes place between the limits cur-
rently selected. Thus it is possible to trace the
operation of a single procedure in a complex sys-
tem.
GLOBALS is run by
!GLOBALS
HEAP is run by
!HEAP
236
Note that the addresses shown for vectors are two
less than the addresses used by the program. For
example if a program called GETVEC and the value
returned was 5874, then the HEAP display would
show a data vector at 5872.
IO is run by
!IO
STACK is run by
!STACK
!STACK ALL
237
The display gives the address and size of the
stack and the number of words used. For each
procedure call in the current chain the following
information is shown:
238
To enter TESTPRO type
!TESTPRO
239
The following sequence may be used, however:
!TESTPRO
#T procedure to be tested
#P parameters for procedure
#ESCAPE
Interrupted
!DEBUG
*K 10T
TRACE
R
Commands
X exits.
240
The D command
The P command
Examples are:
#4PG#X200
241
#5P "string" "STRING"
The R command
The T command
242
Examples are:
#T myproc
#T G115
#T G#X73
#T 5868
#T #X16EC
The X command
243
244
8 Discussion
This section discusses a number of different fea-
tures of the system. They are discussed in alpha-
betical order of topic.
Coroutines
Machine code
Optimising code
Output formatting
Portability
Standardisation
Start-up options
User-defined characters
245
CONVERTING BCPL PROGRAMS
SECTION "ABCD4"
GET "LIBHDR"
GET "ABCDHDR"
246
It is best to declare the program specific
header file after LIBHDR to permit the pro-
gram to redefine names used in LIBHDR. (Al-
ternatively ABCDHDR might include the GET
"LIBHDR" so each program section would just
GET "ABCDHDR".)
247
(8) Compiling the sections of the program. Com-
mon problems include:
(c) S i n g l e q u o t e s h a v e b e e n u s e d r o u n d
strings. In some implementations strings
could be declared in single quotation
marks e.g.
248
(9) When all sections have compiled, the program
can be linked using JOINCIN (and using NEEDCIN
if appropriate to include procedures from LIB)
and tested. One problem at this stage may be
excessive use of stack or storage. The cor-
recting options include:
(b) o v e r l a y i n g t h e p r o g r a m u s i n g L O A D S E G ,
GLOBIN and GLOBUNIN. This is discussed
under ‘Loading and linking code’ in chap-
ter 6.
COROUTINES
Purpose
249
On larger computers these requirements are met by
complex operating systems which can switch control
between different tasks without the task code
knowing that the switch has taken place. Such
systems use a significant proportion of the com-
puter’s power, and although they are very con-
venient for independent tasks they introduce con-
siderable complexity into tasks which need to work
with the same data, or to interact with each
other.
Method
250
A coroutine suspends itself by calling a procedure
which switches processing to another stack. Thus
while waiting, the current state of the coroutine
is held in its stack, terminating with the pro-
cedure which switched stacks. When the coroutine
receives control again its stack becomes the cur-
rent stack and the procedure which suspended the
coroutine returns, causing the processing of the
coroutine to resume from the point at which it
paused.
251
The system establishes the main coroutine before
entering START, but any other coroutine must be
created by the running program. A coroutine is
created by the procedure CREATECO which requires
two parameters:
252
The coroutine procedures
253
INPUT which returns the identity of the
current input stream for use in later
calls to SELECTINPUT;
254
Many BCPL systems support a procedure REWIND,
which re-initialises the current input stream so
that reading restarts at the beginning of the
file. This is not provided in this implemen-
tation, but the same effect can be achieved by
ENDREAD followed by a new FINDINPUT for the same
file.
255
- (STYPE.TERM) if the stream can output part
lines (i.e. if characters written to the
stream are displayed immediately rather than
being buffered up until ‘*N’ is written).
256
In some circumstances it may be useful to deter-
mine the device associated with a stream. If s is
a stream identifier (as returned by FINDINPUT,
INPUT etc.) then s!5 is a number in the range 1
to 7 which identifies the device as follows:
1 /K (keyboard);
2 /C (console);
3 /P (serial port);
4 ERRORSTREAM;
5 /L (printer);
6 /N (null device);
7 /S. (store file);
8 /F. (current filing system file).
257
Other filing systems are much faster (e.g. disk,
Econet), but some operations are less efficient
than others. With both the examples mentioned
reading/writing a complete file in one operation
(using the OSFILE routine) can be up to 10 times
faster than reading/writing it a byte at a time
(using OSBGET/OSBPUT) or a block of bytes at a
time (using OSGBPB). By using store files a file
can be copied into store then read from there (a
byte at a time) by the program. Similarly a
program can write to a store file then copy the
file to the filing system in one operation.
!*DISK
!READ MYFILE
!*TAPE
!SAVE MYFILE
!
258
Two points to beware of are:
259
Three procedures are provided for converting a
vector into a file:
260
INPUT AND TEXT PROCESSING
General input
261
If RDCH or RDBIN read past the end of the input,
they return the constant ENDSTREAMCH (−1) which
cannot represent a valid character.
Field conversion
Input processing
Character processing
String processing
262
SPLIT extracts a string from a larger
string, starting at a given point in
the string and ending just before a
specified delimiting character.
Comments
rdnxt:
ch := RDCH()
SWITCHON ch INTO
$( CASE '*S': CASE '*C': CASE '*N': CASE '*T':
GOTO rdnxt // ignore leading spaces and
// format characters
WHILE '0'<=ch<='9' DO
$( sum := 10*sum + ch - '0'
ch := RDCH()
$)
UNRDCH() // next read to be first char.
// after number
263
Many realtime input processes are designed to
interact with the user at his keystation. However
such interaction is not appropriate if the process
is receiving its input from a command file rather
than directly from a keyboard. The program can
discover whether the current input is interactive
by using TESTSTR to test STYPE.INT. For example:
MACHINE CODE
264
The BCPL system provides four different methods of
entering machine code:
265
It is expected that machine code will normally be
produced by the relocatable assembler, RAS. This
assembler generates relocatable code that is
loaded and linked in the same way as CINTCODE.
The assembler can be used in three ways:
or
266
Note that neither of these bytes is a valid 6502
instruction code and so any machine code calls to
such a procedure must skip past the first byte.
Example
267
SECTION "FINDCH"
PROC "FINDCH"
FINDCH: DB $0D ; special byte
ASL TEXT ; convert to byte addr
ROL TEXT+1
LDY #0
LDA (TEXT),Y ; no. of chars in string
STA MAXIND
LDY STPOS ; index to first char
END
268
This procedure could be called by the following
BCPL code:
SECTION "TESTFC"
GET "LIBHDR"
GLOBAL $( FINDCH:300 $)
LET START() BE
TEST FINDCH("ABCDEFAB", 3, 'A') = 7 THEN
WRITES("OK*N")
ELSE
WRITES("Not OK*N")
269
When entering machine code starting with the spe-
cial byte CF hex, the system checks whether the
global FAULTROUTINE (global 205 declared in
SYSHDR) is defined. If it is then the contents
are assumed to be the word address of the fault
routine to be used and the equivalent byte address
is set up in the fault routine vector.
270
- The fault routine can jump to the standard
BCPL fault routine (or its permanent replace-
ment) by:
JMP ($40E)
JMP ($410)
JMP ($402)
271
SECTION "FAULTY"
PROC "FAULTY"
FAULTY: DB $CF ; special byte
CPX #0 ; is parameter 0 ?
BNE GENFLT
CPY #0
BNE GENFLT
RTS ; normal return
END
272
Code to run at a fixed address
SELECTINPUT( INPUT())
SELECTOUTPUT( OUTPUT())
273
- The display mode must not be changed.
274
PROCB GLOBAL 300
Page 0 usage
or
LDA #<FRED ; low byte of FRED
275
The solution is to define a word containing the
byte address of FRED and then set up the required
values at runtime. For example:
WDFRED: DS 2
BYFRED: DW FRED ; byte address of FRED
CLC
LDA BYFRED+1
ROR A ; shift hi byte right
STA WDFRED+1
LDA BYFRED
ROR A ; repeat for low byte
STA WDFRED
or
Serial re-usability
COUNT: DB 0
INC COUNT
276
Another feature to avoid is changing the contents
of relocated data since this will cause incorrect
values to be set up the next time the code is
relocated. Thus a statement such as:
BYFRED: DW FRED
LDA #<(−2)
STA G300 ; low byte
LDA #>(−2)
STA G300+1 ; high byte
277
OPTIMISING CODE
- to maximise performance;
In particular:
278
Factors likely to reduce CINTCODE size
SECTION "CHOPGV"
GET "LIBHDR"
GET "SYSHDR"
LET START() BE
$( LET GVADDR = (@MAXGLOB)-2
LET NEWMG = READN() // read highest global
// required
LET ENDGV = (GVADDR+NEWMG+4) & #XFFFE
279
MAXGLOB := NEWMG
UNLESS ENDGV = GVADDR!0 DO
$( ENDGV!0 := GVADDR!0
ENDGV!1 := 0
GVADDR!0 := ENDGV
$)
$)
databuffer!0 := 0
MOVE( databuffer, databuffer+l, 50)
280
Repeated calculation such as:
is slower than:
281
(6) Do not include procedure calls in the par-
ameters of other procedure calls.
proc1( a, b, proc2())
c := proc2()
proc1( a, b, c)
OUTPUT FORMATTING
282
WRITEDB writes a decimal double word positive
integer.
283
The use of WRITEF
DECIMAL HEX
1000 03E8
2000 07D0
LET argerror =
"*NERROR IN ARGUMENT NUMBER %N: %S"
284
(4) The format string can be varied, and applied
to the same set of parameters. Thus an error
routine might be:
Graphics
PORTABILITY
285
(3) CINTCODE portability. The compiled CINTCODE
can be run unchanged in the new environment.
286
- If possible, avoid use of features that cannot
be supported on all target operating systems
e.g. assuming that console output is displayed
as it is written rather than being buffered
until a carriage return.
287
For CINTCODE portability follow the suggestions
for source code portability, and in addition:
Explanation
288
Machine characteristics
Word length
289
Programmers of portable software should therefore
avoid using byte addressing on numeric data, which
in any case is normally considered to be bad
practice for other reasons.
Character sets
290
Operating systems
STANDARDISATION
BCPL level 0
291
BCPL standard extensions supported
Extension A1
Character constants *C, *B and *E (but the
latter is now used for ‘escape’ rather than
its original meaning of ‘output buffered char-
acters’).
Extension A2
Character operator %.
Extension A4
Optional compilation using $$tag, $<tag and
$>tag.
Extension A6
SECTION and NEEDS. NEEDS directives can be
satisfied by the utility NEEDCIN.
Extension A7
Store allocation using GETVEC, FREEVEC, MAXVEC
and STACKSIZE.
Extension A8
Scaled arithmetic using MULDIV.
Extension A12
System services with OPSYS.
Extension A3
Field selectors are not supported.
Extension A5
Compound assignment is not supported.
292
Extension Al0b) - Binary I/O
Binary I/O by RDBIN and WRBIN is not fully
supported. RDBIN and WRBIN are provided but
without the defined method of separating rec-
ords in binary streams.
Extension A11
Direct access I/O is not supported.
Extension A13
Floating point is not supported, but is avail-
able as an additional package (which conforms
to Extension Al3b) - Floating Point Procedure
Packet).
293
START-UP OPTIONS
294
The way to avoid the problem is always to in-
itialise static variables as part of the program
initialisation. Thus code such as:
STATIC $( COUNT=0 $)
LET START() BE
$( ...
...
COUNT := COUNT + 1
...
...
$)
STATIC $( COUNT=? $)
LET START() BE
$( COUNT := 0
...
...
COUNT := COUNT + 1
...
...
$)
295
One further point to note is that although local
procedure names and labels are technically static
variables they may not be assigned to. If it is
required to assign to them they must be made
global. For example, the following code would not
compile:
GET "LIBHDR"
LET PROCA() BE
$( ... $)
AND PROCB() BE
$( PROCA := WRCH $)
GLOBAL $( PROCA:300 $)
USER-DEFINED CHARACTERS
296
Although this facility is intended for extra
character definitions it may be used by a program
which wants to reserve a fixed area of memory for
its own use.
SECTION "CHARDEF"
GET "LIBHDR"
GET "SYSHDR" // for SYSINDEX and I.xxx
LET START() BE
$( UNLESS SYSINDEX!I.DEFSPACE = 768 DO
$(
// SYSINDEX!I.DEFSPACE is number of words
// reserved or to be reserved.
FOR I = 1 TO 8 DO
OPSYS( 138, 0, "CHARDEF*C"%I)
CALLBYTE( SYSINDEX!I.RESTART)
$)
// space now reserved - make it usable for
// character definitions
OPSYS( 20, 1, 0)
etc.
$)
297
The specific points to note are:
byteaddr := OPSYS(131)
298
9 Getting Started
This chapter describes how to install the BCPL
Language ROM and how to get the BCPL system work-
ing. It then describes some exercises to intro-
duce a new user to the features of the BCPL
CINTCODE system. New users are urged to work
through these exercises in the order given (some
exercises depend on the results of earlier
exercises).
299
All examples in this chapter use the convention
that computer output is underlined. All user
input is terminated by the RETURN key unless
otherwise stated. User input shown in bold type
means that the key indicated should be pressed.
Thus COPY would mean that the COPY key should be
pressed, whereas if it were not in bold type it
would mean that the characters ‘C’, ‘O’, ‘P’ and
‘Y’ should be entered.
300
(4) Carefully move the keyboard towards the front
of the computer to reveal the four sockets on
the front right of the main printed circuit
board. (Be careful not to strain the multi-
way cable linking the keyboard to the main
circuit board while doing this.)
301
Inserting the BCPL ROM
302
If the ROM is not the right-most language ROM then
the computer should start up as normal. Typing
‘*BCPL’ (followed by RETURN) should enter the BCPL
system and ‘BCPL’ followed by the prompt ‘!’
should be displayed.
Initial checking
303
Press ESCAPE. The message
Interrupted
SETTING UP DISKS
*** ERROR: X
304
The BCPL disk should contain the following files
(in alphabetical order):
305
Since a maximum of 31 files can be held on a disk
there is no room for user files on the BCPL disk.
One possible method of working is to hold all user
files on one or more disks separate from the BCPL
disk. For program development it is likely to be
more convenient to split the BCPL files over one
or more disks, with each disk containing a mixture
of BCPL and user files. A split into two disks (a
‘source’ disk and a ‘test’ disk) is suggested, and
this split is assumed in the exercises given later
in this chapter.
Source disk
Test disk
306
Note that the files JOIN and OPT are not copied to
either the source disk or the test disk. These
files are only rarely used and are accessed from
the BCPL disk when needed.
(3) Copy the files for the source disk into store
until there is no space left e.g.
!READ BCPL
!READ BCPLARG
!READ BCPLCCG
!READ BCPLSYN
!READ BCPLTRN
!READ ED
Error 51
!
!SAVE BCPL
!SAVE BCPLARG
!SAVE BCPLCCG
!SAVE BCPLSYN
!SAVE BCPLTRN
307
(6) Remove the source disk and insert the BCPL
disk. Reboot the BCPL system by pressing
BREAK to delete all the files in store (an
alternative is to use the DELETE command e.g.
!DELETE BCPL
!DELETE BCPLARG
etc.).
!READ ED
!READ ENCODEB
etc.
!*CAT
308
(1) Reboot the system by pressing BREAK.
!ED PROGA
SECTION "PROGA"
GET "LIBHDR"
LET start() BE
WRITES("Hello world*N")
309
(4) Exit from the screen editor by pressing CTRL-
f8 (i.e. pressing the CTRL key and function
key 8 together). Then:
!STORE
4612 UL ED
56 PROGA
Data 0 Free 5329 + ... = 6824
!SAVE PROGA
310
To correct the file return to step (3), but
this time the command ‘ED PROGA’ displays the
file that was created. Chapter 4 describes
the editor commands available to alter text.
(7) !STORE
!SAVE CODEA
!CODEA
311
The program used is the example program ENCODEB
which has been copied from the BCPL disk to the
source disk. This program copies text from one
file to another, encoding the text as it does so.
The encoding algorithm is simply to replace ‘a’
with ‘z’, ‘b’ with ‘y’ ... ‘z’ with ‘a’. The
encoded text can be converted back to its original
form by running the program on it a second time.
!TYPE ENCODEB
SECTION "ENCODE"
GET "LIBHDR"
MANIFEST $( avsize = 20 $)
LET start() BE
$( LET ch = ?
LET infile, outfile = ?, ?
LET argvec = VEC avsize
infile := FINDINPUT(argvec!0)
IF infile = 0 THEN
STOP(RESULT2) // invalid in file
outfile := FINDOUTPUT(argvec!1)
IF outfile = 0 THEN
STOP(RESULT2) // invalid out file
SELECTINPUT(infile)
SELECTOUTPUT(outfile)
312
ch := RDCH()
WHILE ch NE endstreamch DO
$( WRCH( codechar(ch) )
ch := RDCH()
$)
313
Compiling the ENCODE program
!SAVE ENCODE
!READ LIBHDR
314
(1) !ENCODE LIBHDR /C
315
The program is now reading from the console so
all lines typed in are now read as data rather
than as commands. Thus the lines ‘ABCDE’ and
‘fghij’ are read as data. A special facility
is provided by the BCPL system to allow ‘end-
of-file’ to be read from the console - when
cursor editing is disabled the COPY key acts
as end-of-file. Thus the final line of the
example (pressing COPY followed as usual by
RETURN) causes ENCODE to read ENDSTREAMCH from
its input stream and terminate.
!TYPE CONFILE
and
!TYPE /S.CONFILE
!TYPE /F.CONFILE
316
If the store file is deleted by
!DELETE CONFILE
then
!TYPE CONFILE
317
One further device that is useful if you have a
printer is ‘/L’. This is an output device that
directs output to the printer (but not to the
screen). It takes note of the printer ignore
character that is specified by the *FX 6 command.
Output to the screen (device ‘/C’) can be copied
to the printer in the usual way by entering
CTRL-B/CTRL-C.
(1) !ENCODE
(2) !ENCODE /C /K
(4) !ENCODE /Z /C
318
Interrupting a program and use of TIDY
!ENCODE LIBHDR /C
!CONT
!ENCODE /C CONFILE
ABCDE
fghij
319
At this point COPY still has its cursor editing
function and so there is no way of entering ‘end-
of-file’. The solution is to press ESCAPE and
then:
Interrupted
!*FX 4,1
!CONT
!ENCODE LIBHDR /C
!TIDY
!STORE
320
DEBUGGING
!READ LIBHDR
!READ ENCODE
Entering DEBUG
321
To initiate the debugging session enter the
following commands:
!LINK ENCODE
!INIT LIBHDR RDHBIL
!DEBUG
*
*X
!DEBUG
*
*MP CODECHAR
= 5003
*B
*K
TRACE
*CTRL-N
*0T
322
The ‘MP’ command searches for the specified pro-
cedure, which is found at word address 5003 (this
value may be different in different systems). The
‘B’ command sets a breakpoint at the start of this
procedure. The ‘K’ command selects the ‘trace
calls and returns’ option, which means that each
procedure call and return will be reported. The
next line sets page mode (so that output is not
scrolled off the screen before it can be studied).
Finally the command ‘0T’ means start tracing and
continue until ESCAPE is pressed or a breakpoint
is reached.
START called;
SELECTINPUT called;
SELECTOUTPUT called;
323
RDCH called and returns 10 (this is the value
of ‘*N’ (new line), the first character in
LIBHDR);
Displays
*5123:
*$X:
*$C:
324
The command:
*D
*$D5113:
*?
*10F
325
It is possible to break out of DEBUG to use other
utilities then re-enter it and carry on. Exit
from DEBUG using the ‘X’ command and then run the
utility IO:
*X
!IO
!DEBUG
*$C8348:
*0B
*0C
326
The first command cancels the breakpoint. The
second runs the program until it completes or
ESCAPE is pressed. The program takes a few
seconds to complete. When it does so exit from
DEBUG and display the output file produced, noting
that the first few characters are as noted above:
*X
!TYPE RDHBIL
!TIDY
HEAP MANAGEMENT
- store files;
- input/output streams;
- program stacks;
327
The utility HEAP displays the use of the heap.
For example:
!HEAP
!READ HEAP
!READ IO
!READ TESTPRO
!HEAP
328
(3) We will now use TESTPRO to try and allocate a
bigger vector than is available as follows:
!TESTPRO
#T MAXVEC
#R
#T GETVEC
#P 9350
#R
9350 + store needed
!
!DELETE IO
!CONT
9350 + store needed
329
(6) The allocation still fails. A STORE display
shows that although there is enough space in
total there is not a large enough contiguous
area. A HEAP display shows that TESTPRO and
its stack are splitting the free area in two.
!TIDY
!STORE
!SHUFFLE
!STORE
!HEAP
!TESTPRO
#T GETVEC
#P 9500
#R
330
The result is the address of the vector
allocated. Exit from TESTPRO by:
#X
331
Simple use of EX
!COPY /C MYFILE
STORE
*CAT
ESCAPE
Error 1017 Escape
!
!EX MYFILE
!STORE
... usual, store display
!*CAT
... usual disk directory display
!
EX File Terminated
!
332
The commands in the file MYFILE are executed
as if they had been typed in at the console.
MYFILE is not changed in any way. Note that
the STORE display showed a file named $$EX.
This is a temporary file used by the system
and is deleted when the command file ends.
Various other temporary files are used by the
system for other purposes. Their names all
begin with ‘$$’.
(3) U s e t h e E x t r a c t L i b r a r y S e c t i o n s u t i l i t y
NEEDCIN to copy TEMP to EXAMPLE, extracting
various sections from the CINTCODE Library
File LIB and including them in EXAMPLE. (The
sections required are specified by NEEDS di-
rectives in the file EXMP1B.) Save the
CINTCODE file EXAMPLE.
333
First define a command file to perform one com-
pilation. The command file has two parameters -
the number of the source file to be compiled (1, 2
or 3) and an indication of whether the source disk
should be re-inserted after saving the CINTCODE on
the test disk.
.KEY NUMBER/A,MORE
BCPL EXMP<NUMBER>B EXMP<NUMBER>
PAUSE please insert test disk
SAVE EXMP<NUMBER>
DELETE EXMP<NUMBER>
<MORE> PAUSE please insert source disk
!SAVE EXCOMP
334
The third line uses the PAUSE built in command to
suspend the command file while disks are
exchanged. The command file is resumed by the
command CONT. The next two lines save and then
delete the CINTCODE file produced by the com-
pilation. The final line is another PAUSE command
to swap the disks back. If the command file is
run with no value specified for the second par-
ameter MORE then ‘<MORE>’ is deleted from the file
and so the PAUSE is executed. If the value ‘//’
(or REM) is specified for the second parameter,
however, then the line becomes:
EX EXCOMP 1
EX EXCOMP 2
EX EXCOMP 3 //
JOINCIN EXMP1 EXMP2 EXMP3 AS TEMP
NEEDCIN TEMP LIB EXAMPLE
SAVE EXAMPLE
DELETE TEMP
!SAVE EXEXMP
335
To execute the command file:
!EX EXEXMP
!EXAMPLE
336
l0BCPL,CINTCODEand Assembler
This chapter describes the features of the BCPL
language supported in this implementation, and
then discusses the compact interpretive code known
as CINTCODE which is used in this implementation.
Finally the 6502 assembler language is described.
337
The language standard specifies or recommends a
number of general purpose procedures, many of
which are included in this implementation. These
procedures, and the additional procedures pro-
vided, are defined in chapter 5, discussed under
appropriate headings in chapter 8 and summarised
in chapter 11.
Data
Types of data
338
The characters single quote, double quote and
asterisk have special representations ‘*'’, ‘*"’
and ‘**’ respectively. ‘*Xnn’ gives the character
whose hex value is nn (e.g ‘*X20’ gives a space)
and ‘*Onnn’ gives the character whose octal value
is nnn. There are also special representations
for certain control characters - ‘*N’ for newline,
‘*C’ for carriage return, ‘*T’ for tab, ‘*S’ for
space (‘ ‘ is also valid), ‘*B’ for backspace,
‘*P’ for form feed and ‘*E’ for escape.
339
The first byte of the string is preset to the
number of characters in the string. The charac-
ters themselves are stored in subsequent bytes.
Data declarations
340
Static data is stored with the code. It can be
preset by the compiler, and if it is changed by
the program it retains its new value when next
read. The following declaration defines two
static variables:
341
A segment consists of one or more sections, which
are the units of code for compilation. There is a
limit on the size of a section which depends on
the store available for compilation. However any
number of sections may be included in one segment.
Static data can only be addressed within the sec-
tion in which it is declared.
SECTION "sectname"
SECTION "mysect"
NEEDS "libsec1"
NEEDS "libsec8"
342
Data declarations and the GET command
SECTION "prog1"
GET "libhdr"
GET "proghdr"
Procedures
343
With this use of LET and AND, any procedure in the
section can call any other procedure in the
section.
firstprocedure( x)
y := nextprocedure( a, 25)
z := funct( b) /20
var := basicfunction()
var2 := funct( b+3) / basicfunction()
344
Blocks
$( . . . $)
$( LET a = 0
LET b = param1*param2
LET c = ?
IF param3 = 0 THEN . . .
. . .
$)
$(sort
. . .
$)sort
345
Commands within a block
Declarations
LET variable = ?
LET a, b, c = 0, 1, 2
Assignments
y := x*x + 5*x - 3
x, y, z := 0, 2*a+1, −3
346
Conditionals
GOTO label
labela:
Repetitive commands
347
The BCPL commands are:
CASE 'B':
CASE 'C': commands2()
ENDCASE
348
Each case value must be a constant.
Operators
Addressing
349
Arithmetic
* multiply
/ divide (integer division i.e. 19/5 gives 3)
+ add
− subtract
ABS absolute value of next variable
REM remainder after integer division by next
variable (e.g. 19 REM 5 gives 4).
Logical
Conditional
= or EQ
~= or NE or \=
< or LT or LS
<= or LE
> or GT or GR
>= or GE
350
Precedence
()
Procedure call
! (dyadic) e.g. x!y
@ ! (monadic) e.g. !x
* / REM ABS
+ −
= NE < <= > >=
<< >>
NOT
&
|
EQV NEQV
−> , (conditional comma)
TABLE , (comma in a table)
VALOF
Brackets
x := y*(z+3)
t := TIME()
351
Brackets are not used for indexing into arrays.
Only single dimensioned arrays are directly sup-
ported by the language, and these are referenced
using the ‘!’ operator.
Comments
Optional compilation
$<tag . . . $>tag
$$tag
352
It ends if this procedure returns, or if the
statement FINISH is executed, or if one of the
procedures that end a program is called. These
include STOP and ABORT.
CINTCODE
353
The advantages
Portability
Debugging
Decompilation
Protection
354
The instructions of CINTCODE are described in
outline in chapter 11. Their compactness can be
illustrated by the CINTCODE form of the following
statements:
list!i := number
number := RANDOM( number)
355
Two or more CINTCODE files can be joined into a
larger CINTCODE file. This join is performed by
the utility JOINCIN. The larger CINTCODE file may
then be loaded in one operation. JOINCIN is de-
scribed in chapter 4.
Relocation
Overlaying
356
Two additional kinds of hunk are supported for
machine code. These are handled in a similar way
to CINTCODE hunks by the utilities such as JOINCIN
and NEEDCIN, and by the procedures handling
CINTCODE such as LOADSEG and GLOBIN.
Hunk formats
T.END ( 992)
357
CINTCODE and machine code hunks
- body of hunk;
358
Relocation hunks
359
Relocation types 4−7 have similar effects to types
0−3 but with word-relative relocation. Thus if
the relocation type in the example above were 5
the effect of relocation would be to add 650 to
the contents of the word at byte offset 1000 from
the base of the preceding hunk. These relocation
types are not currently used by the assembler.
360
The section name, if present, starts at the third
word in the hunk (i.e. immediately after the
length word). Any NEEDS directives immediately
follow the section name. If there are NEEDS dir-
ectives and no section name the first NEEDS direc-
tive starts at the third word of the hunk.
ASSEMBLER
361
Syntax
362
Expressions
363
The asterisk symbol (*) can be used to represent
the value of the current program counter, which
again is relocatable if in a relocatable section.
364
In normal use, assembler routines called from BCPL
will be assembled in relocatable mode. This is
the default action, and can only be turned off by
using the PHASE directive (see below). Relo-
catable values are labels defined in relocatable
sections or defined via the GLOBAL directive (see
below), while absolute values are numbers or
labels defined in absolute sections.
Examples
365
Addressing modes
366
Absolute Indexed - Assembler syntax: <expr>,X
or <expr>,Y
Zero Page Indexed - Assembler syntax: <expr>,X
or <expr>,Y
If <expr> will fit into a byte, and zero page
indexed mode is allowed for the specified
opcode, then this is used. If <expr> is re-
locatable, contains a forward reference or
will not fit into a byte, an attempt is made
to use the absolute indexed mode if this is
valid. Note however that <expr> must not
start with an opening bracket, otherwise the
assembler will attempt to parse the operand
as an indirect expression. If brackets are
required in <expr> then <expr> should be
preceded by the unary operator ‘+’.
Implied
In this case no operand is required.
367
String - Assembler syntax: "<text>"
This mode is only used by directives. The
<text> may be any set of characters except
asterisk, newline and double quotes. These
are represented by **, *N and *" respectively.
The other special characters listed above may
also be used in strings. There may not be
more than 255 characters in a string.
Directives
ASC <string>
This directive is used to initialise bytes to
characters. The operand must be a string, as
defined above. A byte is allocated for each
character and initialised to the ASCII value
of that character.
Example:
ASC "Table overflow"
DB <expr>
This is used to allocate bytes of memory, and
to fill them with the values given by the
operand. The values specified must each fit
into a byte. A number of bytes may be de-
fined by a single DB instruction by supplying
a list of byte values separated by commas.
Examples:
COUNT DB 0
FLAGS DB $A0|$0F|INTFLG
TABLE DB 'A','B','C','D',0
368
DEPHASE
This statement resets relocatable mode. It
should only be used in conjunction with the
PHASE directive described below. The program
counter is reset to the value it would have
had if the preceding PHASE directive had not
been encountered. This means that space is
allocated for the code produced by PHASE in-
side the current relocatable region, and any
subsequent code is placed after it.
DS <expr>
This directive reserves a number of memory
bytes, which are zeroed. The number of bytes
to be reserved is given by the value of the
operand.
Example:
SAVEAREA DS 6
DW <expr>
This directive is used to allocate two con-
secutive bytes of memory. The first byte is
filled with the low order byte of the value
given by the operand. The second is filled
with the high order byte.
Example:
JMPADR DW $EF20
END
This directive is supplied merely for com-
patibility with other assemblers. The direc-
tive is ignored.
EQU <expr>
This is used to set a label to a value given
by the operand. No code is generated by this
instruction line, but further references to
the label so defined will result in the oper-
and value being used instead. If the <expr>
is relocatable, then so is the defined label.
If the <expr> refers to a GLOBAL value, then
the defined label is also GLOBAL.
369
Examples:
STATUS EQU $EC20
NCHARS EQU (PSIZE−1)*80
EVEN
This forces the program counter to be even, by
inserting a NOP instruction if it is not.
This is required in programs where a pointer
is to be returned as a BCPL address. Since
BCPL addresses are word pointers, the item
being pointed at must be aligned at an even
boundary. Procedures to be called from BCPL
must also start on even boundaries.
GLOBAL <expr>
This directive specifies a label as represen-
ting a BCPL global cell. It must be followed
by an operand which represents the global
number involved. Subsequently the contents of
the BCPL global cell may be referenced by
using the label as an operand, e.g.
370
This enables routines written in assembler to
be called from BCPL. Using a label defined
as GLOBAL in this way also causes the program
counter to be word aligned (an automatic EVEN
directive is executed). Subsequent refer-
ences to a redefined global label refer to the
relevant cell of the BCPL global vector, and
in particular such labels may not be used in
relative addressing modes. A label should be
defined as GLOBAL before it is redefined.
NEEDS <string>
The string given specifies another section
required in conjunction with this one, and is
identical to the NEEDS statement in BCPL. The
NEEDS statement must come after the SECTION
name, if given, but before any code. If the
string is longer than seven characters it is
truncated. It is padded with spaces if it is
shorter than this. The program counter is
word aligned.
Example:
NEEDS "EXIO"
PHASE <expr>
This directive causes the assembler to enter
absolute mode, and is only valid if the
assembler was in relocatable mode (the de-
fault). The program counter is reset to the
value of <expr>. Any labels defined while in
absolute mode will have absolute values, and
the code produced will only run at the loc-
ation indicated by the value of <expr>. The
code is not placed at location <expr> when it
is loaded, however, and this must be done by
the user’s program.
371
PROC <string>
This directive may be used to introduce a
procedure written in assembler in such a way
that it can be identified by the BCPL debug-
ging routines. The operand following it must
be a string, which is truncated or expanded to
seven characters as in NEEDS. It also word
aligns the program counter, so that the entry
point to the procedure is on an even boundary.
SECTION <string>
This directive is similar to PROC, and the
operand must again be a string, which is
forced to seven characters. It identifies a
section of assembler in the same way that the
SECTION statement in BCPL identifies a section
of BCPL. If used, the BCPL debugging routines
will be able to identify the assembler sec-
tion. The program counter is word aligned.
If given, a SECTION directive must be the
first instruction in a program.
STRING <string>
This is used to allocate a BCPL string. The
operand must be a string, as defined above.
The program counter is first word aligned, and
then the length of the string is written out
(as a byte value), followed by the characters
specified in the string.
Examples:
MESS1 STRING "Error in expression"
MESS2 STRING "Type *"HELP*" for help*N"
Instructions
372
Imm Immediate mode - #<expr>
Abs Absolute mode - <expr>
IndI Indexed Indirect mode - (<expr>,X)
IInd Indirect Indexed mode - (<expr>),Y
IndX Absolute Indexed on X - <expr>,X
IndY Absolute Indexed on Y - <expr>,Y
Ind Extended Indirect - (<expr>)
Rel Relative mode - <expr>
Acc Accumulator mode - A
Imp Implied mode
6502 opcodes
373
JMP Abs Ind
JSR Abs
LDA Imm Abs IndI IInd IndX IndY
LDX Imm Abs IndY
LDY Imm Abs IndX
LSR Acc Abs IndX
NOP Imp
ORA Imm Abs IndI IInd IndX IndY
PHA Imp
PHP Imp
PLA Imp
PLP Imp
ROL Acc Abs IndX
ROR Acc Abs IndX
RTI Imp
RTS Imp
SBC Imm Abs IndI IInd IndX IndY
SEC Imp
SED Imp
SEI Imp
STA Abs IndI IInd IndX IndY
STX Abs IndY
STY Abs IndX
TAX Imp
TAY Imp
TSX Imp
TXA Imp
TXS Imp
TYA Imp
XOR Imm Abs IndI IInd IndX IndY
374
l1 Summaries
This chapter summarises the features of the BCPL
CINTCODE system under the following headings:
Assembler
CINTCODE
DEBUG commands
Global variables
Global vector
Manifest constants
Procedures
Tape files
TESTPRO commands
375
ASSEMBLER
Absolute exp
Immediate #exp
Absolute indexed by X exp,X
Absolute indexed by Y exp,Y
Indirect (exp)
Indexed indirect (exp,X)
Indirect indexed (exp),Y
Accumulator A
376
SECTION Section name
STRING BCPL string
$ Hexadecimal
& And
| Or
! Exclusive or
~ Not
< Shift left (binary operator)
< Low order byte (unary operator)
> Shift right (binary operator)
> High order byte (unary operator)
377
BUILT IN COMMANDS AND UTILITIES
ED - the editor
FROM/A,NEW/S
See page 389 for commands.
378
HEAP - display heap
No parameters
REM or
// - comment
Rest of line is ignored.
379
RENAME - rename file
FROM/A,TO/A
380
CINTCODE
b A byte.
n A small number.
w A 16 bit word.
381
($) Addresses in CINTCODE can be refer-
enced either directly or indirectly.
The use of indirect addressing is
shown by a ‘$’ after the instruction
code. Thus there are two Jump instruc-
tions, J and J$.
A b A := A + b
An A := A + n
ADD A := B + A
AG(i) g A := A + G!g
AND A := B & A
AP b A := A + P!b
APn A := A + P!n
APW w A := A + P!w
ATB B := A
ATC C := A
AW w A := A + w
DIV A := B / A
GBYT A := B%A
GOTO Jump to A
J($) l Jump to l
JEQ($) l Jump to l if B = A
JEQ0($) l Jump to l if A = 0
JGE($) l Jump to l if B >= A
JGE0($) l Jump to l if A >= 0
JGR($) l Jump to l if B > A
JGR0($) l Jump to l if A > 0
JLE($) l Jump to l if B <= A
JLE0($) l Jump to l if A <= 0
382
JLS($) l Jump to l if B < A
JLS0($) l Jump to l if A < 0
JNE($) l Jump to l if B NE A
JNE0($) l Jump to l if A NE 0
Kn Call A; P := P + n
KnG(i) g Call G!g; P := P + n
K b Call A; P := P + b
KW w Call A; P := P + w
L b A := b
Ln A := n
LG(i) g A := G!g
LmG(i) g A := G!g!m
LL($) l A := !l
LLG(i) g A := G + g
LLL($) l A := l
LLP b A := P + b
LLPW w A := P + w
LM b A := −b
LMn A := −n
LPn A := P!n
LP b A := P!b
LPW w A := P!w
LmPn A := P!n!m
LSH A := B << A
LW w A := w
MUL A := B * A
NEG A := −A
NOP No operation
NOT A := NOT A
OR A := B | A
PBYT B%A := C
383
REM A := B REM A
RSH A := B >> A
RTN Return
RV A := !A
RVn A := A!n
RVPn A := P!n!A
Sn A := A − n
SG(i) g G!g := A
S0G(i) g G!g!0 := A
SL($) l l := A
SP b P!b := A
SPn P!n := A
SPW w P!w := A
ST !A := B
STn A!n := B
STPn P!n!A := B
STmPn P!n!m := A
SUB A := B − A
SWB SWITCHON A (binary chop switch)
SWL SWITCHON A (range switch)
384
The CINTCODE instruction set
0 32 64 96
(00) (20) (40) (60)
0(00) -- K LLP L
1(01) -- KW LLPW LW
2(02) BRK S0G S0G1 S0G2
3(03) K3 K3G K3G1 K3G2
4(04) K4 K4G K4G1 K4G2
5(05) K5 K5G K5G1 K5G2
6(06) K6 K6G K6G1 K6G2
7(07) K7 K7G K7G1 K7G2
385
128 160 192 224
(80) (A0) (C0) (E0)
0(00) LP SP AP A
1(01) LPW SPW APW AW
2(02) -- -- -- --
3(03) LP3 SP3 AP3 L0P3
4(04) LP4 SP4 AP4 L0P4
5(05) LP5 SP5 AP5 L0P5
6(06) LP6 SP6 AP6 L0P6
7(07) LP7 SP7 AP7 L0P7
386
DEBUG COMMANDS
387
0T Trace until ESCAPE pressed
Vn Variable n
W Unload debug overlay e.g. remove statis-
tics collection
X Exit (return to command state)
Z * Clear collected statistics
? Display current state
= Display current variable
: Display 8 words
:n Display n words
$C Set output to characters
$D Set output to decimal
$O Set output to octal
$X Set output to hex
'a Character a
#octal Octal number
#Xhex Hex number
+ − * / %(REM)
Arithmetic operators
& | Logical operators
! Indirection operator
< > Shift (one bit) operators
388
ED AND TED COMMANDS
Cursor
control
keys Move cursor
TAB Insert spaces to next tab stop
DELETE Delete character to left of cursor
RETURN Split current line
f1 Delete character at cursor position
f2 Delete word
f3 Previous page
f4 Next page
f5 Start/end of page
f6 Start/end of line
f7 Previous word
f8 Next word
f9 Quit (abandon all changes)
CTRL f0 Verify (regenerate display)
CTRL f1 Delete to end of line
CTRL f2 Delete line
CTRL f3 Top of file
CTRL f4 Bottom of file
CTRL f5 Open new line
CTRL f6 Join line
CTRL f7 Undo changes to current line
CTRL f8 Exit
389
Extended commands (ED only)
390
RP command Repeat command until error or any key
pressed
S Split line at cursor position
SB Show block
SE Show end of block
SV /s/ Save all text to file
T Top of file
TS n Set tab spacing
WB /s/ Write block to file
n command Repeat command n times
RP (command; command ...) or
n (command; command ...)
Repeat group of commands
391
ERROR NUMBERS AND TRAP CODES
Error numbers
392
17 store file not found. This error code is
normally returned only when trying to access
a store file specifically e.g. TYPE /S.FRED
would give this error if FRED did not exist,
whereas TYPE FRED would give error 27 since
it would look in the current filing system
after looking unsuccessfully in store.
18 illegal device specified to RENAME command
or procedure (e.g. /L).
19 RENAME of store file - ‘FROM’ file does not
exist or ‘TO’ file already exists.
20 cannot open, link or delete store file -
file is already open or linked. One common
cause of this error is specifying the same
file for input and output (e.g. COPY FRED
FRED). Once the file has been opened for
input the attempt to open it for output
fails.
23 delete function not allowed on specified
device (e.g. DELETE /L would give this
error).
27 file does not exist in current filing system
(see the comments for error 17).
30 the command file being executed contains the
command INIT or CONT.
40 general error return from utilities (e.g.
compilation failed because of errors in the
source).
45 RAS - fatal error. This error indicates a
program failure and should not normally
occur.
50 call of READ, READVEC or FILETOVEC with
‘from’ device neither store nor the current
filing system (e.g. the command READ /P XXX
would cause this error).
51 not enough store to get vector or vector too
small. This error is generated by GETVEC if
it fails to get a vector and also by the
procedures FILETOVEC, READ, READVEC, SAVE,
SAVEVEC and VECTOFILE if they fail because
there is not enough store or the supplied
vector is not big enough.
393
52 device not recognised. A device/file name
begins with ‘/’ but the next character is
not one of the devices recognised by the
system. This error is also generated if the
‘.’ separating ‘/S’ or ‘/F’ from the file-
name is omitted.
54 unable to load CINTCODE - end of file
reached prematurely. The most likely cause
is loading a CINTCODE file which has been
accidentally truncated.
55 unable to load CINTCODE - invalid format.
The most likely cause is trying to LOAD,
LINK or execute a file which is not a
CINTCODE file.
56 unable to link CINTCODE. The file being
linked uses or defines a global variable
beyond the end of the global vector. This
error might arise if the global vector has
been cut down for some reason or if global 0
has been corrupted (global 0 holds the maxi-
mum global number - normally 767).
57 unable to link CINTCODE. The link data in
the file is corrupt. It is likely that the
file has been corrupted at some time.
59 cannot link file as file is not loaded.
This error could be caused by a program
calling GLOBIN without first calling
LOADSEG.
60 attempt to use input device for output or
vice versa (e.g. TYPE /L).
61 GLOBUNIN was called to unlink a file which
was not linked.
62 cannot unlink file - bad link data. This
error probably means that the file has been
overwritten in store. To recover from this
error the system may have to be restarted.
99 ED - fatal error. This error indicates a
program failure and should not normally
occur.
101 cannot write to store file - no room.
103 EXTSFILE or VECTOFILE called with a non-heap
vector. Only vectors obtained from the heap
by GETVEC may be used in these calls.
394
104 EXTSFILE, SAVE, SAVEVEC or VECTOFILE called
with vector containing invalid byte count in
word 1. The count is either negative or, in
the case of EXTSFILE and VECTOFILE, too big
for the size of the heap vector.
105 attempt to select a non-existent stream or
to read from an output stream or write to an
input stream. The most likely cause is
closing a stream (by ENDREAD or ENDWRITE)
then attempting to select it or read from it
or write to it.
106 attempt to close a non-existent stream.
This should not normally occur.
110 CALLCO to an active coroutine.
111 RESUMECO to an active coroutine.
112 DELETECO of an active coroutine.
113 the system cannot re-allocate the reserved
heap area used by SAVE. This indicates a
system failure and should not occur.
114 the first parameter to the procedure VDU is
invalid. This parameter should be a string
composed of numbers or percent signs sep-
arated by commas or semicolons.
121 FREEVEC - attempt to free non-existent vec-
tor. This error is generated if the
parameter to FREEVEC is an address outside
the heap.
122 heap corrupt. If this error occurs the
system must be restarted. A possible cause
is a program writing beyond the end of a
heap vector.
123 APTOVEC - no room in stack.
124 invalid parameter to GETVEC. The parameter
is either negative or greater than 32763.
125 SHUFFLE found heap vector marked as movable
but not part of a file. A possible cause is
a program writing beyond the end of a heap
vector or writing to vector!(−1). The
system will probably have to be restarted.
130 store file linkage corrupt. A possible
cause is a program writing beyond the end of
a heap vector. The system must be
restarted.
395
131 linked files linkage corrupt. A possible
cause is a program writing beyond the end of
a heap vector. The system must be re-
started.
Trap codes
396
S Stack overflow. This may be caused by ac-
cidental recursion or it may simply be that
the default stack size of 400 words is too
small for the needs of the program, in which
case STARTINIT should be used to obtain a
bigger stack.
397
GLOBAL VARIABLES
ABORTCODE (4 S)
ABORTLABEL (5 S)
ABORTLEVEL (6 S)
See the description of the procedure ABORT in
chapter 5.
CNSLINSTR (52 L)
Initialised by the system to a console input
stream. It may be selected by a program in
error conditions but should not be used in
normal circumstances. This stream is used by
DEBUG for its input and so if used by a pro-
gram being tested with DEBUG strange inter-
actions may occur.
CNSLOUTSTR (53 L)
Initialised by the system to a console output
stream. It may be selected by a program
whenever output to the screen is required.
CURRCO (22 S)
The current coroutine. It may be useful to
return this identifier when COWAIT returns
control to a parent coroutine.
ERRORSTREAM (58 S)
The stream that is selected for input fol-
lowing ENDREAD and for output following
ENDWRITE. Also selected by SELECTINPUT(0) and
SELECTOUTPUT(0). Any attempt to read from or
write to this stream causes an ABORT.
398
LASTERROR (21 S)
Set to the error code returned by the last
program run from a command file. May be
tested by a program run from a command file to
see whether the previous program completed
successfully or not.
LIBBASE (117 S)
The address of the start of the runtime
library procedures.
MAXGLOB (0 S)
Contains the maximum global number that may be
used. Since MAXGLOB is global 0 the ex-
pression ‘@MAXGLOB’ may be used as the address
of the global vector.
MCRESULT (11 L)
Holds the A register and flags following a
call to machine code using CALL or CALLBYTE.
If a fault has occurred while in machine code
then it holds #XFFnn where nn is the fault
code. MCRESULT is used by the system for
various purposes and may be changed by any
library procedure. Also used to return
information from the procedure FSTYPE.
RESULT2 (15 L)
Gives a second result in addition to the
normal return parameter from a function. For
example RESULT2 holds the remainder returned
by MULDIV, additional information from
TESTFLAGS and TESTSTR and error return codes
from a number of other procedures.
SYSINDEX (18 S)
Pointer to an area of system information. See
the description of STARTINIT in chapter 5 for
examples of use.
399
GLOBAL VECTOR
LIBHDR
ABORT 23 N Y
ADVAL 201 N/L -
CALL 31 N -
CALLBYTE 121 N -
CALLCO 43 N/L Y
CAPCH 59 N Y
CNSLINSTR 52 D Y
CNSLOUTSTR 53 D Y
COMPCH 42 N Y
COMPSTRING 95 N Y
COWAIT 44 U Y
CREATECO 45 U Y
DELETECO 46 U Y
DELFILE 64 N Y
ENDREAD 71 N Y
ENDWRITE 72 N Y
ENVELOPE 129 N/L -
FILETOVEC 125 N -
FINDARG 96 N Y
FINDINPUT 66 N Y
FINDOUTPUT 67 N Y
FREEVEC 25 N Y
400
NAME NUMBER TYPE CP/M-COMPATIBLE
GETVEC 26 N Y
GLOBIN 100 U Y
GLOBUNIN 101 U Y
INPUT 73 N Y
LEVEL 27 N Y
LOADSEG 104 N Y
LONGJUMP 28 N Y
MAXVEC 29 N Y
MCRESULT 11 D -
MODE 115 U -
MOVE 36 N Y
MULDIV 37 N Y
NEWLINE 84 N Y
NEWPAGE 85 N Y
OPSYS 35 N -
OUTPUT 74 N Y
RANDOM 111 N Y
RDARGS 97 N Y
RDBIN 75 N Y
RDCH 76 N Y
RDITEM 98 N Y
READ 169 N -
READN 78 N Y
READVEC 168 N -
READWORDS 106 N Y
RENAME 70 N Y
RESULT2 15 D Y
RESUMECO 47 N/L Y
RUNPROG 118 U -
SAVE 123 N -
SAVEVEC 204 N -
SELECTINPUT 79 N Y
SELECTOUTPUT 80 N Y
SOUND 128 N/L -
SPLIT 99 N Y
START 1 S Y
STARTINIT 3 S Y
STOP 2 U Y
TESTFLAGS 108 N Y
TESTSTR 77 N/L Y
TIME 112 N/L -
TRAP 38 N Y
401
NAME NUMBER TYPE CP/M-COMPATIBLE
UNRDCH 83 N Y
VDU 200 N/L -
VECTOFILE 126 N -
WRBIN 81 U Y
WRCH 82 U Y
WRITED 88 N Y
WRITEF 90 N Y
WRITEHEX 91 N Y
WRITEN 92 N Y
WRITES 94 U Y
WRITEWORDS 109 N Y
SYSHDR
ABORTCODE 4 D Y
ABORTLABEL 5 D Y
ABORTLEVEL 6 D Y
APTOVEC 127 N/L -
BACKMOVE 219 N/L -
BACKMVBY 218 N/L -
CLIINSTR 33 D -
COLIST 166 D -
CONTPRG 149 U -
COMMON2 62 D/S -
COMMON3 63 D/S -
CURRCO 22 D -
DELXFILE 65 N -
ENDPROG 24 N/L Y
ENDTRAP 34 U Y
ERRORMSG 202 U/S -
ERRORSTREAM 58 D Y
EXTSFILE 102 N -
FAULTROUTINE 205 S -
FINDXINPUT 68 N -
FINDXOUTPUT 69 N -
FSTYPE 39 U/S -
HEAP 48 D -
HEAPEND 54 D -
LASTERROR 21 D -
402
NAME NUMBER TYPE CP/M-COMPATIBLE
LIBBASE 117 D -
LINKEDFILES 114 D -
MAINSTACK 20 D -
MAXGLOB 0 D Y
MOVEBYTE 213 N -
SHUFFLE 203 U -
STACKSIZE 30 N/L Y
STOREFILES 16 D -
STREAMCHAIN 17 D -
SYSINDEX 18 D Y
TIDYSTATE 208 D -
TRAPSTACK 19 D Y
TRAPSTART 122 S Y
UNLOADSEG 105 U Y
VDUINFO 116 N/L -
WRITEA 86 U Y
WRITEBA 87 U Y
WRITEDB 89 N/L Y
WRITEOCT 93 N/L Y
WRITET 40 N/L Y
WRITEU 41 N/L Y
403
MANIFEST CONSTANTS
BITSPERWORD (16 S)
The number of bits in a BCPL word.
BYTESPERWORD (2 S)
The number of bytes per word in strings.
CONSOLE.KEY (1 L)
A mask bit used with TESTFLAGS to find if
there has been a new key depression on the
console.
DV.F (8 S)
DV.S (7 S)
Device codes for use in calling DELXFILE,
FINDXINPUT and FINDXOUTPUT.
ENDSTREAMCH (−1 L)
The result returned by RDCH/RDBIN when a
stream is exhausted.
FIRSTFREEGLOBAL (250 L)
The number of the first global available to
the user.
GLOBWORD (−888 L)
When the system starts up all globals are
initialised to this value. When a global
procedure is unlinked the global is set to
this value. The value does not correspond to
a valid address and is negative, so for most
practical purposes a global containing this
value can be assumed to be in its initial
state.
404
Because globals used to hold data are not re-
initialised when a program is unlinked, it is
dangerous to assume that because a global does
not contain this value it is initialised to a
global procedure address.
I.DEFSPACE (12 S)
I.RESTART (13 S)
See ‘User-defined characters’ in chapter 8.
I.RSTATE (7 S)
See description of STARTINIT in chapter 5.
MAXINT (32767 S)
The most positive number which may be held in
a BCPL word.
MININT (−32767 S)
The most negative number which may be held in
a BCPL word.
MORE.INPUT (2 L)
A mask bit used with TESTFLAGS to find if
more input can be read without physical
input.
M.TRAPESC (2 S)
M.TRAPGV (4 S)
See description of STARTINIT in chapter 5.
R.MCST (0 S)
See description of STARTINIT in chapter 5.
STYPE.TERM (4 L)
STYPE.INT (8 L)
These are for use with TESTSTR to determine
the characteristics of the current streams.
See the description of TESTSTR in chapter 5.
TICKSPERSEC (100 L)
The number of clock ticks in a second. Used
to convert values obtained by TIME into
seconds.
405
PROCEDURES
Coroutines
406
Input and text processing
Output formatting
NEWLINE()
NEWPAGE()
WRBIN( binarycharacter)
WRCH( character)
WRITEA( wordaddress)
WRITEBA( byteaddress)
WRITED( integer, fieldwidth)
WRITEDB( doubleinteger)
WRITEF( format, a, b, c, d, e, f, g, h, i, j, k)
WRITEHEX( integer, fieldwidth)
WRITEN( integer)
WRITEOCT( integer, fieldwidth)
WRITES( string)
407
WRITET( string, fieldwidth)
WRITEU( unsignedinteger, fieldwidth)
WRITEWORDS( source, words)
Runtime control
ABORT( aborttype)
res := APTOVEC( procedure, size)
ENDPROG( endcheck)
FREEVEC( vector)
vector := GETVEC( vectorsize)
stackpointer := LEVEL()
LONGJUMP( stackpointer, label)
max.free.vector := MAXVEC()
stack.size.left := STACKSIZE()
START( parameter)
stacksize.requ. := STARTINIT()
STOP( returncode)
TRAP( traptype, letter)
Utility procedures
408
result := MULDIV( a, b, c)
result := a*b/c
result2 := remainder
XY := OPSYS(A, XY)
mcresult := flags and A
string.words.used := PACKSTRING( fromunpacked,
tostring)
(PACKSTRING is in OPT)
PUTBYTE( string, byteposition, byte)
(PUTBYTE is in OPT)
randominteger := RANDOM( randominteger)
res := RUNPROG( writefstring, param1, param2,
param3, param4)
SHUFFLE( delete.unprotected.files)
SOUND( sound.table)
time := TIME()
UNPACKSTRING( fromstring, tounpacked)
(UNPACKSTRING is in OPT)
VDU( string, a, b, c, d, e, f, g, h, i, j)
size := VDUINFO( rows.or.cols)
409
TAPE FILES
EX // small utilities
JOIN
OPT
Examples
410
TESTPRO COMMANDS
Commands are:
R Run test.
X Exit.
411
412
Appendix
This appendix contains details of many of the
internal data areas and procedures used by the
BCPL system. It also contains details of the
operating system interfaces used, hints on writing
command-state programs and and the effects of
running in the second 6502 processor using the
Tube.
System procedures
413
RUNNING IN THE SECOND 6502 PROCESSOR
414
The data areas are described under the following
headings:
Heap
Language RAM
Miscellaneous
Page 0
Stacks
Store files
System index
Heap
415
The format of the first two words of each area is:
word 0: 0
word 1: −1
416
Language RAM
Despatch routine
417
LDNEXT: ; process next instruction
LDY #0
LDA ($06),Y ; next instruction
ZZTRAP: TAY
INC $06 ; update PC
BEQ LDNEX4
LDNEX2: LDX $BE00,Y ; index to jump table
STX $52 ; save in work area
LDX $BF00,Y
STX $53
JMP ($52) ; process instruction
LDNEX4: INC $07
BNE LDNEX2
Miscellaneous
418
PRGENDLABEL (8) } the current recovery point.
PRGENDLEVEL (7) } LONGJUMP is used to transfer
control here in a variety of
circumstances.
Page 0
Words 0− 6:
current state *
Word 7 :
word address of the global vector
Word 8 :
byte address of RESULT2
Word 9 :
byte address of MCRESULT
Word 10 :
byte address of FAULTROUTINE
Words 11−16:
flags *
Words 17−18:
limits *
Words 19−25:
last saved trap state *
Words 26−28:
trap count *
Words 29−30:
count*
Word 31 :
flag indicating length of last
jump/call/return instruction (used by
DEBUG):
-ve 1 byte
0 2 bytes
+ve 3 bytes
Words 32−38: last saved run state *
419
Words 39−40: last jump addresses *
Words 41−44: interpreter work area (may be used as
temporary storage by machine code
routines if required but must not be
accessed by CINTCODE)
Words 45−55: reserved for use by future packages
(e.g. floating point)
Words 56−71: available for users
Words 72 on: used by operating system.
Stacks
420
Word 0: used when the stack is not the current
stack to save the value of the stack
pointer (initialised to point to word 5 of
the stack)
Word 1: the parent stack (when a stack is created
by CREATECO this word is set to CURRCO;
when a stack is created for START it is
set to −1)
Word 2: the COLIST chain word. Address of next
stack in the chain or 0
Word 3: address of the main procedure for the
stack (i.e. START or the first parameter
to CREATECO)
Word 4: size of the stack
Word 5: address of the stack (i.e. pointer to word
0).
Store files
421
The format of a file data block is:
422
Word 3: address of the ‘close routine’. This
routine is called when the stream is
closed (by ENDREAD, ENDWRITE or TIDY)
with two parameters - 0 and the SCB
address (when the routine is called the
stream is no longer one of the currently
selected streams). It does not return a
result.
Word 4: type word:
bit 0: set for an input stream
bit 1: set for an output stream
bit 2: set for a terminal stream
bit 3: set for an interactive stream
Word 5: device:
1 /K (keyboard read a key at a time)
2 /C (console)
3 /P (serial port)
4 /E (errorstream)
5 /L (printer)
6 /N (null device)
7 /S. (store file)
8 /F. (current filing system file)
Word 6: c u r r e n t b u f f e r p o s i t i o n . For input
streams this is the byte offset within
the buffer of the next character to read.
For output streams it is the byte offset
within the buffer of where the next char-
acter is to be written.
Word 7: buffer limit. The byte offset of the
last position in the buffer.
Word 8: address of the buffer for the stream.
423
For streams accessing current filing system files
the following extra words are used:
424
Also note that output to the screen and the serial
port bypasses the stream control block altogether.
WRCH, WRBIN and WRITES are replaced by alternative
versions which call OSWRCH directly.
Associated globals
System index
425
I.LIBBASE (0) address of the start of the BCPL
library in the ROM
I.TRST (2) address of the trap count. When a
run-state program traps the reason
is stored in the trap count area.
Several traps may occur on the
same CINTCODE instruction so the
first byte of the area is a count
of the number of traps and succ-
essive bytes contain letters iden-
tifying the traps as follows:
B abort
E attempt to restart program after
fatal trap/program end without
re-initialising
G call of uninitialised global
procedure
I requested trap on next instruc-
tion
J requested trap on next jump
K requested trap on next procedure
call/return
L breakpoint reached
N count reached
S stack overflow
X non-existent CINTCODE instruc-
tion
Z divide by zero.
426
I.FLAGS (3) address of the flags area used
mainly by DEBUG. Note that these
flags are ignored unless the ap-
propriate bits in the current
state are set (see below). The
structure of this six-word area
is:
−3 no program to start
−2 fatal trap
−1 abort
0 program ended
1 program initialised
2 breakpoint
3 requested trap on next
instruction/jump/call/return
or count up
4 ESCAPE pressed
5 run out of heap space
6 PAUSE command executed
5: if word 3 is non-0 this word is
decremented on each jump/call/
return.
I.LIMIT (4) address of limits area. This is a
two-word area. Word 0 contains
the negative of the address of the
top of the current stack. Word 1
contains the negative of the maxi-
mum allowable value of the stack
pointer.
427
I.CSTATE (5) address of the current state area.
This area is used by the inter-
preter for the registers etc. used
by CINTCODE. Its structure is
described below.
I.TSTATE (6) address of the last saved trap
state. This area is used to save
the current state for the command
state while the system is in the
run state.
I.RSTATE (7) address of the last saved run
state. This area is used to save
the current state for the run
state while the system is in the
command state. When testing a
program with DEBUG this area may
be examined to determine the state
of the program.
I.TIME (8) address of the count area. This
area is a double-word count of the
number of jumps/calls/returns made
(in the format described for
WRITEDB in chapter 5).
I.JADD (9) address of the last jump addresses
area. This area holds the ‘from’
and ‘to’ byte addresses involved
in the last jump/call/return. It
is used by DEBUG.
I.DEFSPACE (12) the number of words to be reserved
for extra character definitions
(see chapter 8).
I.RESTART (13) the byte address to call (using
CALLBYTE) to restart BCPL reser-
ving space for extra character
definitions (see chapter 8).
428
Current state
429
System saved data
430
The first 141 words are only valid when the system
is in the run state. The second 141 words are
only valid when the system is in the trap state.
SYSTEM PROCEDURES
CHANGECO (32)
Swaps coroutines. Called by:
p1 := CHANGECO( p2, cortn)
Control returns to the statement after the
call but the current stack is now cortn. p2
is copied to p1. If cortn is −1 it performs
an end of program trap.
CLOSESTREAM (120)
Closes a stream. Called by:
CLOSESTREAM( stream)
CONTPRG (149 S)
Called by debugging utilities to continue the
current run-state program. It saves the
command-state globals in SYSDATA, restores the
run-state globals and calls ENDTRAP (see
below). On return from ENDTRAP it saves the
run-state globals in SYSDATA and restores the
command-state globals (except that it always
reselects CNSLINSTR and CNSLOUTSTR as the
current streams). Called by:
res := CONTPRG( par)
where res and par are as for ENDTRAP.
431
ENDTRAP (34 S)
Enters the run state from the command state.
Called by:
res := ENDTRAP( par)
where par is either 0 (in which case execution
resumes with the instruction at the run-state
program counter) or a CINTCODE instruction
code (in which case this instruction is ex-
ecuted as if it were the instruction at the
run-state program counter). Control returns
to the caller when the run-state program traps
or finishes. res is the trap type as listed
under I.FLAGS on page 427.
FILENAME (60)
Parses a device/filename string and strips off
the device prefix (if any). The ‘pure’ file
name is set up as a BCPL string in the buffer
pointed to by global FNAMBUF (12). The string
is followed by a byte containing OD hex.
Called by:
dev := FILENAME( string, type)
432
FINDSTFILE (148)
Checks if a store file of a given name exists.
Called by:
fcb := FINDSTFILE( string)
If a store file called string exists then fcb
is set to the address of the file control
block, otherwise it is set to 0.
RDTOBLOCK (209)
Reads from the current input stream into a
vector. Called by:
eof := RDTOBLOCK( vector, count)
count bytes are read into the vector starting
at address vector+2. vector!1 contains the
number of bytes actually read. eof is TRUE if
the end of the input stream has been reached
(i.e. if the next read would give
ENDSTREAMCH).
SFCNTRL (113)
Performs miscellaneous operations on store
files. Five types of call:
433
SFSTATE (124)
Returns information about a store file.
Called by:
bit.set := SFSTATE( fcb, mask)
fcb is a store file file control block. mask
is a bit mask with bits as follows:
bit 0: file is open for read
bit 1: file is open for write
bit 2: file is linked
bit 3: file is loaded.
bit.set is TRUE if at least one of the bits in
mask is true for the file. The values of all
the bits for the file are stored in MCRESULT.
STRCNTL (61)
Opens a stream. Called by:
scb := STRCNTL( name, type, dev, bsize)
name is the stream name.
type is 1 for input, 2 for output.
dev is −1 if name has not been stripped of any
device prefix, else it is the device code
returned by FILENAME (see above). Note that
it must not be 0.
bsize only applies to output store files and
is the required file data block size or −1 if
the file data blocks are to be as big as
possible.
scb is the address of the stream control block
or 0 for failure.
TRAPSTART (122)
The equivalent of START for command-state
programs. See ‘Writing command-state pro-
grams’ in this Appendix for more details.
TRUNCVEC (103)
Given a vector in the format of a file data
block, it truncates the vector if it is bigger
than it need be to hold the data content.
Called by:
TRUNCVEC( vector)
434
USE OF OPERATING SYSTEM ROUTINES
435
Opening a stream
Closing a stream
436
For single-character reads from the current filing
system:
Writing to a stream
(1) O S B Y T E ( # X F 5 ) t o r e a d t h e p r i n t e r i g n o r e
character. Carry on only if this is not the
character to be printed;
(2) OSWRCH to write CTRL-A (send next character to
printer only);
(3) OSWRCH to write the specified character.
437
Selecting a stream
For SELECTINPUT:
For SELECTOUTPUT:
Otherwise:
438
(4) OSFILE to read the file’s catalogue infor-
mation;
(5) SELECTOUTPUT to restore the previously se-
lected output stream;
(6) at this stage it may be found that there is
no area big enough to read the file contig-
uously and so it may be read conventionally
as described above;
(7) (depending on FSTYPE) *FX139 calls to select
error/message options as described in
chapter 6;
(8) SELECTOUTPUT to select the console;
(9) (depending on FSTYPE) a message giving the
file name is displayed;
(10) OSFILE to read the file;
(11) SELECTOUTPUT to restore the previously se-
lected output stream.
Otherwise:
Deleting a file
Renaming a file
439
WRITING COMMAND-STATE PROGRAMS
Writing utilities
440
- on program completion TIDY is not called so
the program must ensure it unlinks any files
linked, FREEVECs all vectors obtained by
GETVEC and closes all streams it opens;
441
442
Index
A command files 18,34,35,40,48,
ABORT 36,87,208 70,186,333
ABORTCODE 88 command state 4,14,18,77,440
ABORTLABEL 88 command state programs 440
ABORTLEVEL 88 comments 43,352,362
ABS 350 COMPCH 97,262
addressing modes 366,376 compilation 52
ADVAL 89 compound assignment 346
altering memory 222 COMPSTRING 97,262
AND procedure declaration 343 computer requirements 12
APTOVEC 91 CONT 32,77
arguments 16,136 conditional compilation 352
ASC 368 conditional expression 347
assembler 361 conditional operators 350
assignment 346 console 23,166,316
CONSOLE.KEY 164,404
contiguous store files 43,
B 143,153
BACKMOVE 92 converting BCPL programs 246
BACKMVBY 93 COPY command 33
BCPL 5,337 COPY key 15,23,48,139
BCPL compiler 52 coroutines 48,249
BE 343 COWAIT 98,251
BITSPERWORD 404 CP/M 12,400
block 345 CREATECO 99,252
BREAK command 348 CTRL-B 318
BREAK key 13,206 CTRL-C 318
breakpoints 226 CTRL-N 312
built in commands 14,31,378 CTRL-O 312
BY 348 CTRL-SHIFT 312
BYTESPERWORD 404 CTRL-U 15
CTRL-V 16,39
CURRCO 398
C current filing system 21,33,
calculations 10,227 117,212,257
CALL 94,265 current stack 204
CALLBYTE 95,254,265 current variable 220
CALLCO 96,251 cursor control keys 15,48
CAPCH 96,262
capitalch 96
CASE label 348 D
case (upper and lower) 15,362 data 338
cell 27 DB 368
character constants 339 DEBUG 216,387
CINTCODE 5,353,381 alteration of store 222
CINTCODE instructions 382 breakpoints 226
CNSLINSTR 211,398 calculations 227
CNSLOUTSTR 211,398 counting 228
command arguments 16 displays 230
443
DEBUG (continued) EQV 350
input 219,225 ERRCONT 35,188
limits 230 ERRORMSG 106
memory search 231 error handling 188,189
output 225 error numbers 87,106,163,392
overlays 232 ERRORSTREAM 104,211,398
statistics 233 ESCAPE key 19,20,33,60,77,
traces 235 189,229
debugging 215,321 EVEN 370
declarations 346 event handling 189
DEFAULT label 348 EX 18,70
DELETE command 34 example files 305,312,331
DELETE key 15 *EXEC 18,166
DELETECO 100,253 expressions 363
DELFILE 100,254 EXTSFILE 107,254,260
DELXFILE 101,254
DEPHASE 369
devices 21,22,257 F
disabling trapping on ESCAPE FALSE 338
192 fatal trap 209
disabling trapping on GETVEC fault handling 189,269
failure 194 file control block 210,421
disk filing system 118,299 file data block 210,422
display mode 16,39,128 file name block 210,422
DO 347,348 files & file names 8,21,24,
DS 369 117,209,212,253,305,421
DV.F 102,113,115,404 FILETOVEC 109,254,259
DV.S 102,113,115,404 FINDARG 110,262
DW 369 FINDINPUT 111,253
FINDOUTPUT 112,254
FINDXINPUT 113,254
E FINDXOUTPUT 115,254
Econet filing system 118 FINISH 208,353
ED 57,389 FIRSTFREEGLOBAL 404
editing floating point 10
blocks 66 FOR command 348
cursor movement 61,65 free store management 19,26,
deletion 62,65 193
extended commands 63 FREEVEC 116
find & replace 65 FSTYPE 117,213
formatting 68 function 344
insertion 60,64
starting & stopping 59
ELSE command 347 G
END command 34,77 GE 350
END directive 369 GET directive 54,343
ENDCASE 348 GETBYTE 119
ENDPROG 103,208 getting started 299
ENDREAD 104,254 GETVEC 119,193
ENDSTREAMCH 23,139,262,404 GLOBAL declaration 341
entering BCPL 13,206,294 GLOBAL directive 365,370
ENDWRITE 104,254 global variables & global
ENVELOPE 105 vector 25,198,221,236,279,
EQ 350 341,398,400
EQU 369 GLOBALS 236
444
GLOBIN 121,198 linked files & linking
GLOBWORD 404 CINTCODE 6,25,37,48,50,196
GLOBUNIN 122,198 LOAD 25,38,199
GOTO command 347 loaded files & loading
GR 350 CINTCODE 6,25,38,196
graphics 285 LOADSEG 124,197
GT 350 local variables 340,345
LOGAND 350
LOGOR 350
H LONGJUMP 126,206
header files 28,54,343 LOOP 348
heap 26,236,327,415 lower case letters 15,362
HEAP 236 LS 350
hunk 196,357 LSHIFT 350
LT 350
LV 349
I
IF command 347
INIT 36 M
INPUT 123,254 machine code 11,94,264
input processing 261 MAIN 294
installation 300 main stack 204
installed system files 305 MANIFEST constants 340,404
instruction mnemonics 372,376 MAXGLOB 399
INTO 348 MAXINT 405
IO 237 MAXVEC 127
MCRESULT 189,399
memory map 195
J memory search 231
JOIN 79 MININT 405
JOINCIN 80 MODE command 39
MODE procedure 128
MORE.INPUT 164,405
K MOVE 129
keyboard 23 MOVEBYTE 130
keyword 16,110 MULDIV 130
multitasking 9,249
L
labels 347,362 N
language RAM 417 naming sections & procedures
LASTERROR 35,188,399 360,372
layout of store 195 NE 350
LE 350 NEEDCIN 81
leaving BCPL 13 NEEDS 81,342,371
LET procedure declarations NEQV 350
343 NEWLINE 131,282
LET variable declarations 340 NEWPAGE 131,282
LEVEL 124 NOT 350
LIB 305 null device 23
LIBBASE 200,399
LIBHDR 54,305,343
libraries 7,29,37,81,342 O
limits 230 opcodes 362,373,376
LINK 25,37,199 operands 362
445
operating system commands 14, RENAME command 44
201,214 RENAME procedure 148,254
operating system routines 89, REPEAT 348
117,132,213,273,435 REPEATUNTIL 348
operator precedence 351 REPEATWHILE 348
operators 349 repetitive commands 347
OPSYS 132,254,265 RESULTIS 344
OPT 291,305 RESULT2 399
optimisation of code 278 RESUMECO 149,251
optional compilation 352 RETURN 344
OR 347 REWIND 255
OUTPUT 133,254 ROM filing system 118,294
output formatting 282 root stack 204
overlays 6,357 routines 344
RSHIFT 350
run state 18
P running programs 14,25,187,
PACKSTRING 133 202
page 0 275,419 RUNPROG 31,150,201
PAUSE 40 runtime features 185
PHASE 273,371 RV 349
portability 6,285
printer 23,318
printer ignore character 318 S
PROC 372 SAVE command 44
procedure call 344 SAVE procedure 152,254,258
procedure declaration 343 SAVEVEC 154,254,260
procedures 85,406 scope 341
program development aids 8, second 6502 processor 12,26,
28,215 39,414
PROTECT 25,41 SECTION 54,342,372
protection of store files 25, section brackets 345
41,210 segment 196,342
PUTBYTE 134 SELECTINPUT 155,253
SELECTOUPUT 156,254
serial port 23,33
R SHUFFLE command 27,46
RANDOM 135 SHUFFLE procedure 27,157
RAS 82,361 size of CINTCODE 5,279
RDARGS 16,136,262 size of compilation 54
RDBIN 139,261 SOUND 158
RDCH 139,261 speed 10,280
RDITEM 140,262 SPLIT 159,262
READ command 42 STACK 237
READ procedure 141,254,258 stack overflow 205,252
READN 145,262 stacks 26,203,237,250,281,420
READVEC 146,254,259 STACKSIZE 160,205
READWORDS 147,261 stand-alone programs 11
redefining library procedures standardisation 291
123 START 161,207
relocatable symbols 365 starting 207,294,352
relocation of machine code STARTINIT 162,207
122,198,275,277,359 STATIC variables 294,341
REM 350 statistics 233
REM command 43 STOP 163,208
446
stopping 208,352 upper case letters 15,362
STORE 46 user-defined characters 296
store files 8,21,24,26,46, utilities 51,378
209,257,421
store management 19,26,193
stream control block 211,422 V
streams 21,211,237,253,422 VALOF 344
STRING 372 variables 338
strings 295,339 VDU 171
STYPE.INT 166,405 VDUINFO 173
STYPE.TERM 166,405 VEC declaration 339
SWITCHON 348 VECTOFILE 174,254,260
SYSHDR 305,343 vector, free store 26,193,259
SYSINDEX 399,425 vector, global 25,198,221,
SYSTEM files 37 236,279,341,398,400
system index 399,425 vector, local 339
system procedures 431
system saved data 430
W
WHILE 348
T word size 27,289,338
TABLE 294,339 WRBIN 175,282
tagged section brackets 345 WRCH 176,282
tagged optional compilation WRITEA 176,282
352 WRITEBA 177,282
tape filing system 54,55,118, WRITED 177,283
299,410 WRITEDB 178,283
TED 57,389 WRITEF 179,283,284
TEST 347 WRITEHEX 180,283
testing 215 WRITEN 180,283
TESTFLAGS 164,256 WRITEOCT 181,283
TESTPRO 238,411 WRITES 181,283
TESTSTR 166,255 WRITET 182,283
text processing 261 WRITEU 182,283
THEN 347 WRITEWORDS 183,283
TICKSPERSEC 167,405
TIDY 23,27,48,77
TIME 167 @ 349
TO 348 ! 227,349,364
trace 235 " 339
TRAP 19,168 ' 225,339,363
trap codes 396 $ 363
TRAPSTART 207,440 $$ 352
TRUE 338 $< 352
TYPE 49 $> 352
$( 345
$) 345
U $C 225
UNLESS 347 $D 225
UNLINK 25,50,199 $O 225
unloading code 197 $X 225
UNLOADSEG 169,197 % 172,179,227,349,363
UNPACKSTRING 170 & 172,227,350,364
UNRDCH 171,261 , 172,351
UNTIL 348 ; 172,362
447
: 230 /* 352
( 351 /C 23,257,316
) 351 /F 22,257
+ 227,350,364 /K 23,257
− 227,350,364 /L 23,257,318
−> 347 /N 23,257
:= 346 /P 23,257
= 227,343,350 /S 22,257
~ 350,364 * 227,339,350,364
~= 350 *' 339,363
< 227,350,364 *" 339,363
<= 350 */ 352
<< 350 ** 339,363
> 227,350,364 *B 339,363
>= 350 *C 54,339,363
>> 350 *E 54,339,363
? 16,227,229 *N 54,339,363
\ 350 *P 54,339,363
\= 350 *S 339,363
\/ 350 *T 54,339,363
| 227,350,364 *X 339
|| 352 # 225,338
/ 227,350,364 #B 338
/\ 350 #X 172,225,338
// 43,352
448
BCPL
for the BBC Microcomputer
This is the essential reference manual for the BCPL system on the BBC
Microcomputer. It describes the functions supported by the BCPL
language ROM, and the use of the BCPL Compiler, the Screen Editor, the
Assembler, and the other utilities which are part of the BCPL language
package. It also contains the background information to enable the
most demanding users to take full advantage of the wide range of
features provided.
ISBN 0 907876 10 2
SBD10