RTR logo

BBC BASIC for SDL 2.0

BBC BASIC for Windows

Keywords EOF# to LOMEM



EOF#

A function which will return −1 (TRUE) if the data file whose channel number is the argument is at, or beyond, its end. In other words, when PTR# points beyond the current end of the file. When reading a serial file, EOF# would go true when the last byte of the file had been read.

EOF# is only true if PTR# is set beyond the last byte written to the file. It will NOT be true if an attempt has been made to read from an empty block of a sparse random access file. Because of this, it is difficult to tell which records of a random access file have had data written to them. These files need to be initialised and the unused records marked as empty.

Writing to a byte beyond the current end of file updates the file length immediately, whether the record is physically written to the disk at that time or not. However, the file must be closed in order to ensure that all the data written to it is physically written to the disk.

Syntax

<n-var>=EOF#(<numeric>)

Associated Keywords

OPENIN, OPENUP, OPENOUT, CLOSE#, INPUT#, READ#, BGET#, GET$#, EXT#, PTR#

EOR

An operator returning the bitwise or logical exclusive-or between two items. The two operands are internally converted to 4 byte integers before the EOR operation. For each of the 32 bits EOR uses the following truth-table:
Input AInput BOutput
000
011
101
110
You can use EOR as a logical operator or as a 'bit-by-bit' (bitwise) operator. The operands can be boolean (logical) or numeric.
X=B EOR 4
IF A=2 EOR B=3 THEN 110
BBC BASIC does not have true boolean variables; this can lead to confusion at times (see NOT for more details).

In the example below, the operands are boolean (logical) and the result of the tests (IF) A=2 and (IF) B=3 is either TRUE or FALSE.

The result of this example will be FALSE if A=2 and B=3 or A<>2 and B<>3. In other words, the answer will only be TRUE if the results of the two tests are different.

answer=(A=2 EOR B=3)
The brackets are not necessary, they have been included to make the example easier to follow.

The last example uses EOR in a similar fashion to the numeric operators (+, −, etc).

A=X EOR 11
Suppose X was −20, the EOR operation would be:
11111111 11111111 11111111 11101100
00000000 00000000 00000000 00001011
11111111 11111111 11111111 11100111  = -25

Syntax

<n-var>=<numeric> EOR <numeric>
<n-var>EOR=<numeric>

Associated Keywords

NOT, AND, OR

ERL

A function returning the line number of the line where the last error occurred.
X=ERL
If there was an error in a procedure call, the line number of the calling line would be returned, not the line number of the definition.

The number returned by ERL is the line number printed out when BBC BASIC reports an error.

See the Error Handling sub-section for more information on error handling and correction.

Syntax

<n-var>=ERL

Associated Keywords

ON ERROR, REPORT, ERR

ERR

A function returning the error code number of the last error which occurred (see the section entitled Error messages and codes).
X=ERR
Once you have assumed responsibility for error handling using the ON ERROR statement, you can use this function to discover which error occurred.

See the Error Handling sub-section for more information on error handling and correction.

Syntax

<n-var>=ERR

Associated Keywords

ON ERROR, ERL, REPORT

ERROR

A statement which can 'force' an error to occur. This can be useful for testing or for adding 'user-defined' errors. ERROR is followed by the error number and the error string:
200 ERROR 100,"Fault"
Unless errors are trapped using ON ERROR this will result in the message:
Fault at line 200
and ERR will be set to 100. User-defined errors should normally be given error numbers in the range 100 to 179 so that they don't conflict with the built-in error codes. However, if you specify an error number of zero BBC BASIC will treat it as a fatal error, i.e. it will not be trapped by the ON ERROR statement and will cause the program to end immediately.

Note that the error string is held in a temporary buffer, which will be overwritten if an INPUT, CALL or READ statement is executed, or if BBC BASIC returns to immediate mode. This means you should be careful when accessing the error string using REPORT or REPORT$; if necessary copy it into a conventional string variable first.

ERROR is also used in the ON ERROR, ON ERROR LOCAL and RESTORE ERROR statements.

Syntax

ERROR <numeric>,<string>
ON ERROR <stmt>{:<stmt>}
ON ERROR LOCAL <stmt>{:<stmt>}
ON ERROR OFF
RESTORE ERROR

Associated Keywords

ON ERROR, ON ERROR LOCAL, ERL, ERR, REPORT, RESTORE

EVAL

EV.

A function which applies the interpreter's expression evaluator to the contents of the argument string.
X=EVAL("X^Q+Y^P")
X=EVAL"A$+B$"
X$=EVAL(A$)
In effect, you pass the string to BBC BASIC and say 'work this out'.

You can use this function to accept and evaluate an expression, such as a mathematical equation, whilst the program is running. You could, for instance, use it in a 'calculator' program to accept and evaluate the calculation you wished to perform. Another use would be in a graph plotting program to accept the mathematical equation you wished to plot.

The example below is a 'bare bones' calculator program which evaluates the expression typed in by the user.

PRINT "This program evaluates the expression"
PRINT "you type in and prints the answer"
REPEAT
  INPUT "Enter an expression" exp$
  IF exp$<>"END" PRINT EVAL exp$
UNTIL exp$="END" 
END
Note that EVAL stops parsing the string at the end of the valid expression, so for example EVAL("123ABC") will return 123 and not report an error. If you would prefer the error to be detected, enclose the expression in parentheses e.g. EVAL("(" + expr$ + ")") which will report 'Missing )' in such a case.

You can only use EVAL to work out functions (like SIN, COS, etc). It won't execute statements like MODE 0, PRINT, etc. Note that EVAL may fail if you use it to evaluate a structure member, since the 'dot' after the structure name may cause it to be interpreted as an abbreviated keyword.

If the expression contains variables, you may need to use the REM!Keep compiler directive to ensure the variable names are not changed if the program is 'crunched', for example when building an application bundle.

Syntax

<n-var>=EVAL(<string>)
<s-var>=EVAL(<string>)

Associated Keywords

STR$, VAL

EXIT

EX.

A statement which causes a premature exit from a FOR...NEXT, REPEAT...UNTIL or WHILE...ENDWHILE loop.

EXIT FOR causes execution to continue after the matching NEXT statement, EXIT REPEAT causes execution to continue after the matching UNTIL statement and EXIT WHILE causes execution to continue after the matching ENDWHILE statement. Typically you would use EXIT when a situation occurs which necessitates leaving the loop 'part way through':

FOR I% = start% TO finish%
  ...
  IF bool% THEN EXIT FOR
  ...
NEXT I%

REPEAT
  ...
  IF bool% THEN EXIT REPEAT
  ...
UNTIL condition%

WHILE condition%
  ...
  IF bool% THEN EXIT WHILE
  ...
ENDWHILE
In the case of EXIT FOR an optional loop variable can be specified, causing execution to continue after the NEXT statement which matches that variable:
FOR I% = start% TO finish%
  FOR J% = first% TO last%
    ...
    IF bool% THEN EXIT FOR I%
    ...
  NEXT
NEXT
REM Execution continues here
You can EXIT from a loop even when inside a nested loop of a different kind:
REPEAT
  FOR J% = first% TO last%
    ...
    IF bool% THEN EXIT REPEAT
    ...
  NEXT
UNTIL FALSE
REM Execution continues here
EXIT is not compatible with the use of non-standard FOR...NEXT constructs such as 'popping' an inner loop or listing multiple loop variables after NEXT. When EXIT is used, every FOR must have a matching NEXT.

Syntax

EXIT FOR [<n-var>]
EXIT REPEAT
EXIT WHILE

Associated Keywords

FOR, REPEAT, WHILE

EXP

A function returning 'e' to the power of the argument. The argument must be < 88.7228392 (in *FLOAT 40 mode) or <709.782713 (in *FLOAT 64 mode). The 'natural' number, 'e', is approximately 2.718281828.
Y=EXP(Z)
This function can be used as the 'anti-log' of a natural logarithm. Logarithms are 'traditionally' used for multiplication (by adding the logarithms) and division (by subtracting the logarithms). For example,
log1=LN(2.5)
log2=LN(2)
log3=log1+log2
answer=EXP(log3)
PRINT answer
will calculate 2.5*2 by adding their natural logarithms and print the answer.

Syntax

<n-var>=EXP(<numeric>)

Associated Keywords

LN, LOG

EXT#

A function which returns the total length of the file whose channel number is its argument.
length=EXT#f_num
In the case of a sparse random-access file, the value returned is the complete file length from byte zero to the last byte written. This may well be greater than the actual amount of data on the disk, but it is the amount of disk space allocated to the file by the filing system.

If you want to write extra data at the end of an existing file, you should open the file with OPENUP and then set the file pointer to the end of the existing data:

PTR#channel = EXT#channel
The file must have been opened before EXT# can be used to find its length.

EXT# is also used when accessing a communications port (e.g. a serial port). It returns the number of characters which have been received, but not yet read. To prevent blocking you should attempt to read (with BGET#) no more than this number of characters.

(BBC BASIC for Windows only)
EXT# may also be used on the left of the equals sign to set the file's length:

EXT#channel = newlength

Syntax

<n-var>=EXT#(<numeric>)
EXT#(<numeric>)=<numeric>

Associated Keywords

OPENIN, OPENUP, OPENOUT, CLOSE#, PRINT#, INPUT#, READ#, BPUT#, BGET#, GET$#, PTR#, EOF#

FALSE

FA.

A function returning the value zero.
flag=FALSE
...
IF flag ...
You can use FALSE in a REPEAT....UNTIL loop to make the loop repeat for ever. Consider the following example.
terminator=10
REPEAT
  PRINT "An endless loop"
UNTIL terminator=0
Since 'terminator' will never be zero, the result of the test 'terminator=0' will always be FALSE. Thus, the following example has the same effect as the previous one.
REPEAT
  PRINT "An endless loop"
UNTIL FALSE
Similarly, since FALSE=0, the following example will also have the same effect, but its meaning is less clear.
REPEAT
  PRINT "An endless loop"
UNTIL 0
See the keyword AND for logical tests and their results.

Syntax

<n-var>=FALSE

Associated Keywords

TRUE, EOR, OR, AND, NOT

FILL

A statement which performs a 'flood fill' in the current graphics foreground colour, starting at the specified point and continuing until non-background-colour pixels are found. FILL is followed by the X and Y coordinates of the starting point; the optional qualifier BY indicates that the coordinates are relative (offsets from the current graphics cursor position) rather than absolute.

The operation may appear to fail if the graphics background colour is not available as a 'solid' colour, with the current display settings, and has therefore been approximated by 'dithering'.

FILL x,y is equivalent to PLOT 133,x,y
FILL BY x,y is equivalent to PLOT 129,x,y

FILL is also used with the CIRCLE, ELLIPSE and RECTANGLE statements to indicate that a filled (solid) shape should be drawn, or that a block move rather than a block copy is required.

FILL 400,400

Syntax

FILL <numeric>,<numeric>
FILL BY <numeric>,<numeric>
CIRCLE FILL <numeric>,<numeric>,<numeric>
ELLIPSE FILL <numeric>,<numeric>,<numeric>,<numeric>
RECTANGLE FILL <numeric>,<numeric>,<numeric>,<numeric> [TO <numeric>,<numeric>]

Associated Keywords

BY, CIRCLE, ELLIPSE, GCOL, RECTANGLE

FN

A keyword used to identify a user-defined function. FN is followed immediately by the function name; the first character of the function name may be an underline (or a digit).

A function may take any number of parameters of any type (or none), and may return a string or numeric result. It does not have to be defined before it is used.

A function definition is terminated by '=' used at the beginning of a statement.

The first two examples below are single line function definitions and the third is a multi-line definition:

DEF FN_mean(Q1,Q2,Q3,Q4)=(Q1+Q2+Q3+Q4)/4

DEF FN_fact(N):IF N<2 THEN =1 ELSE =N*FN_fact(N-1)

DEF FN_reverse(A$)
LOCAL B$,Z%
FOR Z%=1 TO LEN(A$)
  B$=MID$(A$,Z%,1)+B$
NEXT
=B$
Functions are re-entrant and the parameters (arguments) are normally passed by value. The keyword RETURN can be used in the function definition to specify that a parameter should instead be passed by reference. Arrays and structures are always passed by reference.

The following function sets the print control variable to the parameter passed and returns a null string. It may be used in a PRINT command to change the print control variable (@%) within a print list.

DEF FN_pformat(N):@%=N:=""
Functions have to return a result, but the value returned by this function is a null string. Consequently, its only effect is to change the print control variable. Thus the PRINT statement
PRINT FN_pformat(&90A) X FN_pformat(&2020A) Y
will print X in G9z10 format and Y in F2z10 format. See the keyword PRINT for print format details.

Single-line functions can be placed anywhere within your program. Multi-line functions must be placed where they will not be executed 'out of sequence', this usually means at the end of the program after the END statement. See the Procedures and functions sub-section for more information.

FN may alternatively be followed by a numeric value contained in parentheses. This causes the function pointed to by the specified value to be called (an indirect call):

fptr% = ^FN_mean()
mean = FN(fptr%)(a, b, c, d)
See the Indirect procedure and function calls sub-section for more information.

Syntax

<n-var>|<s-var>=FN<name>[(<exp>{,<exp>})]
<n-var>|<s-var>=FN(<numeric>)[(<exp>{,<exp>})]
DEF FN<name>[(<n-var>|<s-var>{,<n-var>|<s-var>})]

Associated Keywords

DEF, ENDPROC, LOCAL, PRIVATE, PROC, RETURN

FOR

F.

A statement which initialises a FOR...NEXT loop. The loop is always executed at least once.
FOR temperature%=0 TO 9
FOR A(2,3,1)=9 TO 1 STEP -0.3
The FOR...NEXT loop is a way of repeating a section of program a set number of times. For example, the two program segments below perform identically, but the second is easier to understand.
10 start=4: end=20: step=2
20 counter=start
30 PRINT counter," ",counter^2
40 counter=counter+step
50 IF counter<=end THEN 30
60 ...

10 start=4: end=20: step=2
20 FOR counter=start TO end STEP step
30   PRINT counter," ",counter^2
40 NEXT
50 ...
You must not exit a FOR...NEXT loop with a GOTO (see the sub-section on Program Flow Control for more details). You can force a premature end to the loop with the EXIT statement:
FOR I=1 TO 20
  X=A^I
  IF X>1000 THEN EXIT FOR
  PRINT I,X
NEXT
It is not necessary to declare the loop variable as an integer type in order to take advantage of fast integer arithmetic. If it is an integer, then fast integer arithmetic is used automatically.

Any numeric assignable item may be used as the control variable. In particular, a byte variable (?X) may act as the control variable and only one byte of memory will be used. See the Indirection sub-section for details of the indirection operators.

FOR ?X=0 TO 16: PRINT ~?X: NEXT
FOR !X=0 TO 16 STEP 4: PRINT ~!X: NEXT
Because a single stack is used, you cannot use a FOR...NEXT loop to set array elements to LOCAL in a procedure or function.

Syntax

FOR <n-var>=<numeric> TO <numeric> [STEP <numeric>]

Associated Keywords

TO, STEP, NEXT, EXIT

GCOL

GC.

A statement which sets the graphics foreground or background logical colour to be used in all subsequent graphics operations.
GCOL colour
GCOL mode,colour
GCOL sets the graphics foreground or background colour, and optionally specifies how the colour is to be plotted on the screen. It can be plotted directly, ANDed, ORed or Exclusive-ORed with the colour already there, or the existing colour can be inverted.

When GCOL is followed by one value the graphics foreground or background colour is set, and the plotting mode is set to 'plot'. If the value is less than 128, the graphics foreground colour is set to that value. If the number is 128 or greater, the graphics background colour is set to value−128. There are up to 128 logical colours (numbered 0 to 127), but the number available varies with the mode; see the section on graphics colours for details.

When GCOL is followed by two values the first determines the plotting mode and the second the graphics foreground or background colour. The plotting modes are as follows:
mode=0   Plot the colour specified.
mode=1 OR the specified colour with the colour that is already there.
mode=2 AND the specified colour with the colour that is already there.
mode=3 Exclusive-OR the specified colour with the colour that is already there.
mode=4 Invert the colour that is already there.
mode=5 Do nothing (subsequent plots are a no-op).
mode=6 AND the inverse of the specified colour with the existing colour.
mode=7 OR the inverse of the specified colour with the existing colour.

GCOL 1 : REM sets the graphics foreground colour to 1
GCOL 130 : REM sets the graphics background colour to 2
GCOL 3,4 : REM sets the mode to EOR and the colour to 4
See the Compatibility limitations section for important notes on the use of these plotting modes.

GCOL n is equivalent to VDU 18,0,n
GCOL m,n is equivalent to VDU 18,m,n.

Generally, you will not notice a change in the graphics background colour until you clear the graphics screen with a CLG command.

Syntax

GCOL [<numeric>,]<numeric>

Associated Keywords

CLS, CLG, MODE, COLOUR, PLOT

GET/GET$

A function and compatible string function that read the next character from the keyboard buffer (they wait for the character), or read a character from the screen. GET$ is also used to read a string from a file.

Reading the keyboard

N=GET
N$=GET$
GET and GET$ wait for a 'key' (character) to be present in the keyboard buffer and then return the ASCII value of that key or a string (length=1) containing the character of the key. If there are any characters in the keyboard buffer when a GET or GET$ is issued, then the function will return immediately. See the keyword INKEY for a way of emptying the keyboard buffer before issuing a GET.

GET and GET$ do not echo the pressed key to the screen. If you want to display the character for the pressed key, you must PRINT or VDU it.

If the function and cursor keys have been redefined using the *KEY command, pressing them will load the keyboard buffer with their currently defined character string. Since GET and GET$ remove characters from the keyboard buffer, one character will be returned every time a GET is issued. A single GET will return the first character and leave the rest in the keyboard buffer.

You can use GET and GET$ whenever you want your program to wait for a reply before continuing. For example, you may wish to display several screens of instructions and allow the user to decide when he has read each screen.

REM First screen of instructions
CLS
PRINT .......
PRINT .......
PRINT "Press any key to continue ";
temp=GET
REM Second screen of instructions
CLS
PRINT ....... etc
Note that using GET prevents any events, for example ON CLOSE, from being processed until you press a key. For that reason it is often better to use INKEY instead:
PRINT "Press any key to continue ";
REPEAT temp=INKEY(1):UNTIL temp>0
The default values returned by the function and cursor control keys are listed below:

Backspace9Tab13Enter
128 Ctrl/Left     129Ctrl/Right 130Home 131End
132PgUp 133PgDn 134Insert 135Delete
136Left 137Right 138Down 139Up
140Mouse wheel down 141Mouse wheel up
 
145F1 161Shift/F1 177Ctrl/F1 193Alt/F1
146F2 162Shift/F2 178Ctrl/F2 194Alt/F2
147F3 163Shift/F3 179Ctrl/F3 195Alt/F3
148F4 164Shift/F4 180Ctrl/F4 196Alt/F4+
149F5 165Shift/F5 181Ctrl/F5 197Alt/F5
150F6 166Shift/F6 182Ctrl/F6 198Alt/F6
151F7 167Shift/F7 183Ctrl/F7 199Alt/F7
152F8 168Shift/F8 184Ctrl/F8 200Alt/F8
153F9 169Shift/F9 185Ctrl/F9 201Alt/F9
154F10 170Shift/F10 186Ctrl/F10 202Alt/F10
155F11* 171Shift/F11 187Ctrl/F11 203Alt/F11
156F12* 172Shift/F12 188Ctrl/F12 204Alt/F12
157F13* 173Shift/F13 189Ctrl/F13 205Alt/F13
158F14* 174Shift/F14 190Ctrl/F14 206Alt/F14
159F15* 175Shift/F15    191Ctrl/F15    207Alt/F15

* these codes are also generated from the following key combinations:

155Shift/Tab
156Ctrl/Home
157Ctrl/End
158Ctrl/PgUp
159Ctrl/PgDn

+note that Alt/F4 normally closes the window so does not actually return the code listed. You can make Alt/F4 return code 196 by using the ON CLOSE statement, but beware that this will also prevent you closing the window by clicking on the close button.

The mouse wheel codes (140 and 141) require Windows™ 98 or later.

If you would prefer the Delete key to produce the ASCII code DEL (127) instead of its default value (135) you can achieve that using *KEY as follows:

*KEY 23 |?
(that is, the vertical line or pipe character followed by a question mark).

Reading the screen

N=GET(X,Y)
N$=GET$(X,Y)
GET(X,Y) returns the character at text coordinates X,Y as an ASCII code. GET$(X,Y) returns the character at text coordinates X,Y as a string. The coordinates are with respect to the current text viewport. If the coordinates are outside the viewport GET(X,Y) returns −1 and GET$(X,Y) returns an empty string.

In UTF-8 mode GET$(X,Y) returns a string of length 1, 2 or 3 bytes, depending on the position of the character within the Basic Multilingual Plane.

Note that GET(X,Y) and GET$(X,Y) do not work reliably if the text was written using a proportional-spaced font, or in a mixture of different fonts, or if the font has changed since the text was written.

Reading from a file

A$=GET$#file_channel
GET$ can also be used to read a string from a file. GET$ differs from INPUT# and READ# in that it reads a string terminated by carriage-return (&0D), line-feed (&0A) or NUL (&00) - you cannot tell what the terminator actually was. It also differs in that if a terminator character is not found within 65535 bytes, it returns a string of length 65535 containing the data read up to this point (BBC BASIC for Windows v5.95a only). By contrast, INPUT# and READ# return an empty string in these circumstances, and the data read from the file is discarded. GET$# is therefore more useful if the format of the file is uncertain.

GET$ may optionally be used with the qualifier BY (to specify how many bytes to read from the file) or TO (to specify the terminator character). These override the normal CR, LF or NUL terminators:

dest$=GET$#file_channel BY bytecount%
dest$=GET$#file_channel TO termchar%
The terminator character is specified as its ASCII code, for example to specify a comma terminator use TO 44, TO &2C or TO ASC(","). If you add &100 to the value (e.g. TO &12C) the specified terminator will be recognised in addition to (rather than instead of) the normal CR and LF terminators.

If you add &8000 to the value (e.g. TO &802C) CR (carriage return) will be recognised as a terminator in addition to the specified character (in this example a comma). However LF will not be recognised as a terminator.

Syntax

<n-var> = GET
<s-var> = GET$
<n-var> = GET(<numeric>,<numeric>)
<s-var> = GET$(<numeric>,<numeric>)
<s-var> = GET$#<numeric>
<s-var> = GET$#<numeric> BY <numeric>
<s-var> = GET$#<numeric> TO <numeric>

Associated Keywords

INKEY, INKEY$, INPUT#, READ#, OPENIN, OPENOUT, OPENUP

GOSUB

A statement which calls a section of a program (a subroutine) at a specified line number or label. One subroutine may call another subroutine (or itself).
GOSUB 400
GOSUB (4*answer+6)
GOSUB (mysub)
The only limit placed on the depth of nesting is the room available for the stack.

You may calculate the line number. However, if you do, the program should not be renumbered. A calculated value must be placed in brackets.

Very often you need to use the same group of program instructions at several different places within your program. It is tedious and wasteful to repeat this group of instructions every time you wish to use them. You can separate this group of instructions into a small sub-program. This sub-program is called a subroutine. The subroutine can be 'called' by the main program every time it is needed by using the GOSUB statement. At the end of the subroutine, the RETURN statement causes the program to return to the statement after the GOSUB statement.

Syntax

GOSUB <l-num>
GOSUB (<numeric>)

Associated Keywords

RETURN, ON, PROC

GOTO

G.

A statement which makes BBC BASIC jump directly to a specified line number or label rather than continuing with the next statement in the program.
GOTO 100
GOTO (X*10)
GOTO (mydest)
You should never GOTO a line which is outside the current FOR...NEXT, REPEAT...UNTIL or WHILE...ENDWHILE loop.

If a calculated value is used, the program should not be renumbered. A calculated value must be placed in brackets.

The use of GOTO is deprecated. Uninhibited use will make your programs almost impossible to understand (and hence, debug). It is always possible to find an alternative to using GOTO, and invariably your programs will be improved as a result.

Syntax

GOTO <l-num>
GOTO (<numeric>)

Associated Keywords

GOSUB, ON

HIMEM

A pseudo-variable which contains the address of the first byte above BBC BASIC's program, data and stack memory. The user's program and data grow upwards from LOMEM and the stack grows downwards from HIMEM. If the two meet, an untrappable 'No room' error results. See the Format of data in memory section for more details.

By default, HIMEM is set at slightly less than 2 Mbytes above LOMEM. If this is insufficient for your program and data, you can raise HIMEM (subject to there being sufficient memory in your computer). This is an important difference from other versions of BBC BASIC, in which you must never raise HIMEM above its initial value. Note that INSTALLed libraries are loaded immediately above HIMEM, so if you do raise HIMEM above the value it had when the first library was loaded, all libraries will be removed.

If you need to raise HIMEM don't be tempted to set it to an absolute value (memory addresses are allocated by the Operating System and vary from session to session). Instead always set it relative to the value of PAGE, LOMEM or TOP. For best performance, set HIMEM to an exact multiple of four; you can achieve that by ANDing it with -4 (&FFFFFFFC).

If you need to reserve an area of memory which will not be affected by CHAIN or CLEAR (for example to pass data between programs) you can lower HIMEM from its initial value. The area of memory between the new value of HIMEM and the old value of HIMEM (−1) will not be used by BBC BASIC (except when the INSTALL statement loads the first library).

HIMEM must not be changed within a subroutine, procedure or function; in a FOR ... NEXT, REPEAT ... UNTIL, or WHILE ... ENDWHILE loop nor within a multi-line IF ... ENDIF clause. If you want to change HIMEM, it is better to do so early in your program.

HIMEM = PAGE+10000000
HIMEM = (LOMEM+10000000) AND -4
HIMEM = HIMEM-40

Syntax

HIMEM=<numeric>
<n-var>=HIMEM

Associated Keywords

LOMEM, PAGE, TOP

IF

A statement which tests a condition and controls the subsequent flow of the program depending on the result. It is part of the IF....THEN....ELSE structure. IF statements may be single line or multi-line.

Single-line IF statement

IF length=5 THEN 110
IF A<C OR A>D GOTO 110
IF A>C AND C>=D THEN GOTO 110 ELSE PRINT "BBC"
IF A>Q PRINT"IT IS GREATER":A=1:GOTO 120
The IF statement is the primary decision making statement. The testable condition (A<C, etc) is evaluated, and converted to an integer if necessary. If the value is non-zero the rest of the line (up to the ELSE clause if there is one) is executed. If the value is zero, the rest of the line is ignored, unless there is an ELSE clause in which case execution continues after the ELSE.
IF age<21 THEN PRINT "Under 21"

flag=age<21
IF flag THEN PRINT "Under 21"
The above examples will print "Under 21" if the value of 'age' is less than 21, and do nothing otherwise.
IF age<21 THEN PRINT "Under 21" ELSE PRINT "21 or over"

flag=age<21
IF flag THEN PRINT "Under 21" ELSE PRINT "21 or over"
The above examples will print "Under 21" if the value of 'age' is less than 21, and "21 or over" otherwise.

The keyword THEN is optional in most examples of the single-line IF statement. The exceptions are when THEN is followed immediately by a destination line number, by a pseudo-variable (e.g. TIME) or by an end-of-function (=). However, THEN is mandatory for the multi-line IF statement.

Multi-line IF statement

IF length=5 THEN
  PRINT "length is 5"
ELSE
  PRINT "length is not 5"
ENDIF
A multi-line IF clause is begun by an IF statement which has the keyword THEN as the very last thing on the line (it cannot even be followed by a REMark). It is ended by an ENDIF statement, which must be the first thing on the line. If the integer numeric expression after IF is non-zero, the statements up to the ENDIF (or ELSE clause if present) are executed. If the expression evaluates to zero the statements after ELSE are executed, or if there is no ELSE clause execution continues after the ENDIF statement.

There may be any number of lines between the IF ... THEN statement and the ENDIF statement. Multi-line IF ... ENDIF clauses may be nested.

You can cascade multiple IF ... ENDIF clauses to test a number of different alternatives:

IF x=3 THEN
  PRINT "x is 3"
ELSE IF x=4 THEN
    PRINT "x is 4"
  ELSE IF x=5 THEN
      PRINT "x is 5"
    ELSE
      PRINT "x is not 3 or 4 or 5"
    ENDIF
  ENDIF
ENDIF
but in this situation a CASE statement would be a better choice.

Syntax

IF <t-cond> [THEN <stmt>{:<stmt>}] [ELSE <stmt>{:<stmt>}]
IF <t-cond> GOTO <l-num> [ELSE <l-num>]
IF <t-cond> THEN <l-num> [ELSE <l-num>]
IF <t-cond> THEN
 

Associated Keywords

THEN, ELSE, ENDIF

INKEY/INKEY$

A function and compatible string function which does a GET/GET$, but waits for a specified maximum time rather than indefinitely. INKEY can also be used to test the current state of a specific key (pressed or not pressed).

INKEY or INKEY$ is followed by a numeric argument. If this is zero or positive it indicates the maximum time to wait for a keypress (in units of 10ms). If it is negative it indicates which key should be tested.

INKEY positive or zero argument

INKEY/INKEY$ waits for the specified maximum number of clock ticks of 10ms each. If no key is pressed in the time limit, INKEY will return −1 and INKEY$ will return a null (empty) string. If there is one or more characters waiting in the keyboard buffer, INKEY/INKEY$ will behave exactly the same as GET/GET$. If the specified time limit is zero, INKEY/INKEY$ will return immediately.

The INKEY function returns the ASCII value of the key pressed. The INKEY$ function returns a string (length=1) containing the character corresponding to the key pressed. The values returned by the function and other special keys are tabulated under GET/GET$.

key=INKEY(num)
N=INKEY(0)
N$=INKEY$(100)
If the function and cursor keys have been redefined using the *KEY command, pressing them will load the keyboard buffer with their currently defined character string. Since INKEY and INKEY$ remove characters from the keyboard buffer, one character will be returned every time an INKEY is issued. A single INKEY will return the first character and leave the rest in the keyboard buffer.

INKEY can be used to 'empty' the keyboard buffer. You can do this with the following program line:

REPEAT UNTIL INKEY(0)=-1

INKEY negative argument

If INKEY is followed by a negative argument, the state of a particular key is tested. If the key is currently pressed INKEY will return the value -1 (TRUE); if the key is not pressed INKEY will return the value 0 (FALSE).

The numeric values corresponding to the different keys are as follows (note that these values are as compatible as possible with the BBC Micro and the Acorn Archimedes, allowing for the differences between their keyboards and the PC's keyboard).

A−66 N−86 1−49 [−57 f1−114
B−101 O−55 2−50 ]−89 f2−115
C−83 P−56 3−18 ;−88 f3−116
D−51 Q−17 4−19 '−80 f4−21
E−35 R−52 5−20 #−91 f5−117
F−68 S−82 6−53 ,−103 f6−118
G−84 T−36 7−37 .−104 f7−23
H−85 U−54 8−22 /−105   f8−119
I−38 V−100   9−39 \−121 f9−120
J−70 W−34 0−40 Tab−97 f10−31
K−71 X−67 −24 Bksp−48 f11−29
L−87 Y−69 =−94 Enter−74 f12−30
M−102   Z−98 `−46 Space−99 Esc−113
 
Insert−62 Home−63 PgUp−64 Left−26 Right−122
Delete−90 End−106 PgDn−79 Up−58 Down−42
Shift−1 Ctrl−2 Alt−3 Caps−65 L-shift−4
R-shift−7 L-ctrl−5 R-ctrl−8 L-alt−6 R-alt−9
 
Numeric keypad:
0−107 1−108 2−125   3−109 4−123
5−124 6−27 7−28 8−43 9−44
.−77 +−59 −60 *−92 /−75
Enter−61 Num−78  

Note that the above table corresponds to the standard UK keyboard layout. The US keyboard differs slightly:

`        −80      '        −91     

The mouse buttons can be tested with −10 (left) −11 (middle) and −12 (right)

IF INKEY(-99) PRINT "Space bar pressed"
Important note: On some Operating Systems INKEY with a negative argument works whether or not your program has the input focus. This can occasionally be useful, but often you will prefer to detect a key being pressed only when the user is working with your program. In that case you can check for input focus.

In BBC BASIC for Windows INKEY(-256) returns the value ASC("W"), i.e. 87; in BBC BASIC for SDL 2.0 it returns either ASC("S"), i.e. 83, or ASC("s"), i.e. 115.

Syntax

<n-var>=INKEY(<numeric>)
<s-var>=INKEY$(<numeric>)

Associated Keywords

GET, GET$, MOUSE, WAIT

INPUT

A statement to input values from the keyboard.
INPUT A,B,C,D$,"WHO ARE YOU",W$,"NAME"R$
If the items are not immediately preceded by a printable prompt string (even if null) then a '?' will be printed as a prompt. If the variable is not separated from the prompt string by a comma, the '?' is not printed. In other words: no comma - no question mark.

Items A, B, C, D$ in the above example can have their answers returned on one to four lines, separate items being separated by commas. Extra items will be ignored.

Then WHO ARE YOU? is printed (the question mark comes from the comma) and W$ is input, then NAME is printed and R$ is input (no comma - no '? ').

When the <Enter> key is pressed to complete an entry, a new-line is generated. BBC BASIC has no facility for suppressing this new-line, but the TAB function can be used to reposition the cursor. For example,

INPUT TAB(0,5) "Name ? " N$,TAB(20,5) "Age ? " A
will position the cursor at column 0 of line 5 and print the prompt Name ?. After the name has been entered the cursor will be positioned at column 20 on the same line and Age ? will be printed. When the age has been entered the cursor will move to the next line.

The statement

INPUT A
is exactly equivalent to
INPUT A$: A=VAL(A$)
Leading spaces will be removed from the input line, but not trailing spaces. If the input string is not completely numeric, it will make the best it can of what it is given. If the first character is not numeric, 0 will be returned. Neither of these two cases will produce an error indication. Consequently, your program will not abort back to the command mode if a bad number is input. You may use the EVAL function to convert a string input to a numeric and report an error if the string is not a proper number or you can include your own validation checks.
INPUT A$
A=EVAL(A$)
Strings in quoted form are taken as they are, with a possible error occurring for a missing closing quote.

A semicolon following a prompt string is an acceptable alternative to a comma.

See the input editing section for details of the editing facilities available when entering data in response to an INPUT statement.

Syntax

INPUT [TAB(X[,Y])][SPC(<numeric>)]['][<s-const>[,|;]]
                    <n-var>|<s-var>{,<n-var>|<s-var>}

Associated Keywords

INPUT LINE, INPUT#, GET, INKEY

INPUT LINE

A statement of identical syntax to INPUT which uses a new line for each item to be input. The item input is taken as is, including commas, quotes and leading spaces.
INPUT LINE A$

Syntax

INPUT LINE[TAB(X[,Y])][SPC(<numeric>)]['][<s-const>[,|;]]
                        <s-var>{,<s-var>}

Associated Keywords

INPUT

INPUT#

A statement which reads data in internal format from a file and puts them in the specified variable(s). INPUT# is used with a file or device opened with OPENIN, OPENUP or OPENOUT.
INPUT #E,A,B,C,D$,E$,F$
INPUT #chnl,aux$
It is possible to read past the end-of-file without an error being reported. You should usually include some form of check for the end of the file.

READ# is synonymous with INPUT#. When INPUT# and READ# are used to read strings, they look for a carriage-return terminator (&0D), which is what is written with PRINT#. If the string was written by another program and is terminated with a line-feed character (&0A), then use GET$# instead.

The format of data files differs according to the *FLOAT mode in effect at the time (in *FLOAT 40 mode numeric values are written as 5 bytes, in *FLOAT 64 mode they are written as 8 bytes and in *FLOAT 80 mode they are written as 10 bytes). You must ensure that when numeric values are read with INPUT# (or READ#) the same *FLOAT mode is in effect as when the values were written.

The format of data files is different from files created by Acorn versions of BBC BASIC. If you want to read from an Acorn format data file you can use the following function, which takes the file channel number as a parameter and returns a numeric or string value as appropriate (this works only in the default *FLOAT 40 mode):

DEF FNacorn(F%):LOCAL I%:I%=BGET#F%
IF I%=&40 ?(^I%+3)=BGET#F%:?(^I%+2)=BGET#F%:?(^I%+1)=BGET#F%:?(^I%)=BGET#F%:=I%
IF I%=0 I%=BGET#F%:LOCAL A$:WHILE I% A$=CHR$BGET#F%+A$:I% -= 1:ENDWHILE:=A$
LOCAL N:INPUT #F%,N:IF ?(^N+4)=0 THEN =0 ELSE =N/2
See the Disk files section for more details and numerous examples of the use of INPUT#.

Syntax

INPUT #<numeric>,<n-var>|<s-var>{,<n-var>|<s-var>}

Associated Keywords

INPUT, OPENIN, OPENUP, OPENOUT, CLOSE#, PRINT#, READ#, BPUT#, BGET#, GET$#, EXT#, PTR#, EOF#

INSTALL

A statement which allows you to load a library file containing one or more pre-defined functions and procedures. These functions and procedures can be called by name from within your program, but they do not appear in the program listing. If you, or somebody else, has written a number of useful functions which you might want to call from several different programs, this provides a convenient way of packaging and distributing them.

Because the procedures and functions do not form part of your program the size of its file is reduced, and if a bug is found in one of the functions it can be corrected by updating the library file without having to modify each of the programs from which it is called.

You can INSTALL as many library files at the same time as you like, subject to there being sufficient memory. These libraries remain resident until the BASIC program's window is closed (they are not cleared by a CHAIN statement). If two or more libraries contain a procedure or function of the same name, the one used is that in the last library loaded.

The libraries are loaded above HIMEM so if you raise HIMEM above the value it had when the first library was INSTALLed, all the libraries will be removed from memory.

A library file is a standard BBC BASIC internal-format (tokenised) program file except that it should normally contain only procedure and function definitions. Line numbers and labels are not recognised in library files, therefore the GOTO and GOSUB statements cannot be used, and the only variant of the RESTORE statement which is useful is the RESTORE +n form used in conjunction with LOCAL DATA and RESTORE DATA.

You should normally prefix the filename with either @lib$ (for standard libraries) or @dir$ (for libraries specific to your program) so that the file will be loaded from the correct location irrespective of the current directory setting. See the Library routines section for details of the supplied libraries.

INSTALL @lib$+"arraylib"
INSTALL @dir$+"mylib"
INSTALL checks to see if the library is already loaded, and if so it does nothing. Note that a case-sensitive comparison of the supplied path/filename is performed, so the same library being specified differently will not be detected.

Syntax

INSTALL <string>

Associated Keywords

HIMEM, FN, PROC

INSTR

A function which returns the position of a sub-string within a string, optionally starting the search at a specified place in the string. The leftmost character position is 1. If the sub-string is not found, 0 is returned.

The first string is searched for any occurrence of the second string.

There must not be any spaces between INSTR and the opening bracket.

X=INSTR(A$,B$)
position=INSTR(find_in$,look_for$)
Y=INSTR(A$,B$,Z%) :REM START AT POSITION Z%
You can use this function for validation purposes. If you wished to test A$ to see if was one of the set 'FRED BERT JIM JOHN', you could use the following:
set$="FRED BERT JIM JOHN"
IF INSTR(set$,A$) PROC_valid ELSE PROC_invalid
The character used to separate the items in the set must be excluded from the characters possible in A$. One way to do this is to make the separator an unusual character, say CHR$(127).
z$=CHR$(127)
set$="FRED"+z$+"BERT"+z$+"JIM"+z$+"JOHN"

Syntax

<n-var>=INSTR(<string>,<string>[,<numeric>])

Associated Keywords

LEFT$, MID$, RIGHT$, LEN

INT

A function truncating a real number to the lower integer.
X=INT(Y)

INT(99.8) = 99
INT(-12) = -12
INT(-12.1) = -13
This function converts a real number (one with a decimal part) to the nearest integer (whole number) less than or equal to the number supplied. Thus,
INT(14.56)
gives 14, whereas
INT(-14.5)
gives −15.

Note: INT truncates towards minus infinity but assignment to an integer variable truncates towards zero. Thus:

x% = INT(-14.5)
PRINT x%
x% = -14.5
PRINT x%
prints -15 and -14 respectively.

Syntax

<n-var>=INT<numeric>

Associated Keywords

None

LEFT$

A string function which returns the left 'num' characters of the string. If there are insufficient characters in the source string, all the characters are returned. LEFT$ may also be used to the left of an equals sign to change the leftmost part of a string whilst leaving the rest alone.

There must not be any spaces between LEFT$ and the opening bracket.

newstring$=LEFT$(A$,num)
A$=LEFT$(A$,2)
A$=LEFT$(RIGHT$(A$,3),2)
LEFT$(A$,3) = B$
For example,
name$="BBC BASIC"
FOR i=3 TO 9
  PRINT LEFT$(name$,i)
NEXT
END
would print
BBC
BBC 
BBC B
BBC BA
BBC BAS
BBC BASI
BBC BASIC
LEFT$(A$,0) returns an empty string; LEFT$(A$,-1) returns the original string unmodified.

When using LEFT$ on the left of an equals sign, and the expression to the right of the equals sign evaluates to a string with fewer characters than the specified sub-string length, only that number of characters is changed. For example:

A$ = "BBC BASIC"
LEFT$(A$,3) = "ZZ"
will set A$ equal to "ZZC BASIC". Although the sub-string length is set to three, only two characters are actually modified since that is the length of the string "ZZ".

LEFT$(A$) is shorthand for LEFT$(A$,LENA$-1), in other words it returns or sets all but the last character of A$.

Syntax

<s-var>=LEFT$(<string>[,<numeric>])
LEFT$(<s-var>[,<numeric>])=<string>

Associated Keywords

RIGHT$, MID$, LEN, INSTR

LEN

A function which returns the length of the argument string.
X=LEN"fred"
X=LENA$
X=LEN(A$+B$)
This function 'counts' the number of characters in a string. For example,
length=LEN("BBC BASIC")
would set 'length' to 9.

LEN is often used with a FOR....NEXT loop to 'work down' a string doing something with each letter in the string. For example, the following program looks at each character in a string and checks that it is a valid hexadecimal digit.

valid$="0123456789ABCDEF"
REPEAT
  INPUT "Type in a HEX number" hex$
  flag=TRUE
  FOR i=1 TO LEN(hex$)
    IF INSTR(valid$,MID$(hex$,i,1))=0 flag=FALSE
  NEXT
  IF NOT flag THEN PRINT "Bad HEX"
UNTIL flag

Syntax

<n-var>=LEN(<string>)

Associated Keywords

LEFT$, MID$, RIGHT$, INSTR

LET

A statement indicating an assignment to a string or numeric variable (or an array element or structure member). LET can normally be omitted, and must be omitted in the case of assignment to the pseudo-variables LOMEM, HIMEM, PAGE, PTR# and TIME.

LET was mandatory in early versions of BASIC. Its use emphasised that when we write

X=X+4
we don't mean to state that X equals X+4 - it can't be, but rather 'let X become equal to what it was plus 4':
LET X=X+4
Most modern versions of BASIC allow you to drop the 'LET' statement. However, if you are writing a program for a novice, the use of LET makes it more understandable.

Syntax

[LET] <var>=<exp>

Associated Keywords

None

LINE

A statement which draws a straight line between two points in the current graphics foreground colour. LINE is followed by the X and Y coordinates of the ends of the line.
LINE 100,200,300,400
This will draw a straight line from the point 100,200 to the point 300,400.

LINE x1,y1,x2,y2 is equivalent to MOVE x1,y1 : DRAW x2,y2

The keyword LINE is also used in the INPUT LINE statement. LINE INPUT is synonymous with INPUT LINE.

Syntax

LINE <numeric>,<numeric>,<numeric>,<numeric>
LINE INPUT [TAB(X[,Y])][SPC(<numeric>)]['][<s-const>[,|;]]
                        <s-var>{,<s-var>}

Associated Keywords

DRAW, INPUT, MOVE, PLOT

LN

A function giving the natural logarithm of its argument.
X=LN(Y)
This function gives the logarithm to the base 'e' of its argument. The 'natural' number, 'e', is approximately 2.71828183.

Logarithms are 'traditionally' used for multiplication (by adding the logarithms) and division (by subtracting the logarithms). For example,

log1=LN(2.5)
log2=LN(2)
log3=log1+log2
answer=EXP(log3)
PRINT answer
will calculate 2.5*2 by adding their natural logarithms and print the answer.

Syntax

<n-var>=LN<numeric>

Associated Keywords

LOG, EXP

LOCAL

A statement to declare variables for local use inside a function (FN) or procedure (PROC).

LOCAL saves the value(s) of the specified variable(s) on the stack, and initialises the variables to zero (in the case of numeric variables) or null (in the case of string variables). The original values are restored from the stack on exit from the function or procedure (i.e. at '=' or ENDPROC). The variables need not have been previously declared.

An entire array may be made LOCAL, following which it is in an undimensioned state. Before the local array can be used within the function or procedure it must be dimensioned using a DIM statement. The new dimensions can be the same as or different from those of a global array with the same name. LOCAL arrays are allocated on the stack, and are freed when the function/procedure is exited.

Similarly an entire structure may be made LOCAL, following which it is in an undeclared state. Before the local structure can be used within the function or procedure it must be declared using a DIM statement. The new format (number and type of members) can be the same as or different from that of a global structure with the same name. LOCAL structures are allocated on the stack, and are freed when the function/procedure is exited.

See also PRIVATE which is similar to LOCAL except that the variables hold their values from one call of the function/procedure to the next, rather than being initialised to zero/null each time.

LOCAL A$,X,Y%,items()
If a function or a procedure is used recursively, the LOCAL variables will be preserved at each level of recursion.

LOCAL DATA

LOCAL DATA saves the current DATA pointer on the stack (but leaves its value unchanged). When used inside a FOR...NEXT, REPEAT...UNTIL or WHILE...ENDWHILE loop, or inside a user-defined function, procedure or subroutine, the data pointer is automatically restored to its original value on exit. Otherwise it can be restored using the RESTORE DATA statement.
LOCAL DATA
RESTORE +1
DATA "Here", "is", "some", "local", "data"
READ A$, B$, C$, D$, E$
RESTORE DATA

LOCAL is also used in the ON CLOSE LOCAL, ON ERROR LOCAL, ON MOUSE LOCAL, ON MOVE LOCAL, ON SYS LOCAL, ON TIME LOCAL, DIM LOCAL and RESTORE LOCAL statements.

Syntax

LOCAL <n-var>|<s-var>|<array()>{,<n-var>|<s-var>|<array()>}
LOCAL <struct{}>{,<struct{}>}
LOCAL DATA

Associated Keywords

DEF, DIM, ENDPROC, FN, ON, PRIVATE, PROC

LOG

A function giving the base-10 logarithm of its argument.
X = LOG(Y)
This function calculates the common (base 10) logarithm of its argument. Inverse logarithms (anti-logs) can be calculated by raising 10 to the power of the logarithm. For example, if x=LOG(y) then y=10^x.

Logarithms are 'traditionally' used for multiplication (by adding the logarithms) and division (by subtracting the logarithms). For example,

log1=LOG(2.5)
log2=LOG(2)
log3=log1+log2
answer=10^log3
PRINT answer

Syntax

<n-var>=LOG<numeric>

Associated Keywords

LN, EXP

LOMEM

A pseudo-variable which controls where in memory the dynamic data structures are to be placed. The default is TOP, the first free address after the end of the user's BASIC program.
LOMEM = LOMEM+100
PRINT ~LOMEM :REM The ~ makes it print in HEX.
Normally, dynamic variables are stored in memory immediately after your program (see the section entitled Format of data in memory). You can change the address where BBC BASIC starts to store these variables by changing LOMEM.

USE WITH CARE. Changing LOMEM in the middle of a program causes BBC BASIC to lose track of all the variables you are using.

Syntax

LOMEM=<numeric>
<n-var>=LOMEM

Associated Keywords

HIMEM, TOP, PAGE

Left CONTENTS

CONTINUE Right


Best viewed with Any Browser Valid HTML 3.2!
© Richard Russell 2021