Uses of the semicolon in BBC BASIC

for discussion of bbc basic for windows/sdl, brandy and more
Post Reply
User avatar
Richard Russell
Posts: 1246
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Uses of the semicolon in BBC BASIC

Post by Richard Russell » Mon Nov 11, 2019 11:31 pm

I'm posting this for no other reason than that it interests me. I'm strange like that. :wink:

BBC BASIC uses the semicolon character (;) in several different ways, but they all* come under the general category of 'suppress forthcoming action'. Here are the ones that I know about:
  1. Suppress right-justifying the following numeric value:

    Code: Select all

          PRINT ;number
  2. Suppress outputting a newline terminator:

    Code: Select all

          PRINT number;
  3. Suppress writing an LF terminator to the file:

    Code: Select all

          BPUT#file, s$;
  4. Send a 16-bit value rather than 8-bit (*perhaps this is the exception):

    Code: Select all

          VDU 25,5,123;456;
  5. Suppress waiting for the external command to complete, and return immediately (BB4W/BBCSDL extension):

    Code: Select all

          *run command;
  6. Suppress creating a new level of IF nesting (BB4W/BBCSDL extension):

    Code: Select all

          IF <condition> THEN
            <statements>
          ELSE IF <condition> THEN;
            <statements>
          ELSE IF <condition> THEN;
            <statements>
          ENDIF
    
Have I missed any?

User avatar
jgharston
Posts: 3927
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by jgharston » Tue Nov 12, 2019 8:41 am

Supress the absence of a question mark in INPUT.
INPUT "Prompt: "A$ gives Prompt: _
INPUT "Prompt: ";A$ gives Prompt: ?_
INPUT "Prompt: ",A$ gives Prompt: ?_

Collect flags from SYS call:
SYS call[,in[,in...]] [TO [out[,out...]] [; flags]]

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
Richard Russell
Posts: 1246
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by Richard Russell » Tue Nov 12, 2019 9:24 am

jgharston wrote:
Tue Nov 12, 2019 8:41 am
Supress the absence of a question mark in INPUT.
Simply an alternative to a comma, I think; not sure why semicolon is accepted here at all.
Collect flags from SYS call:
SYS call[,in[,in...]] [TO [out[,out...]] [; flags]]
That's a new one on me. I assume it's a RISC OS feature and if so it must have a very untypical ABI (returning multiple values is unusual enough, without the option of returning 'flags'). How does that map to a language like C which (as far as I'm aware) makes no such provision?

User avatar
dhg2
Posts: 148
Joined: Tue Oct 25, 2016 8:37 pm
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by dhg2 » Tue Nov 12, 2019 12:11 pm

This is a complete guess but I have the impression RISC OS is mostly written in assembly language, so the multiple return values possibly correspond to the contents of the ARM registers presumably starting at r0, and I assume 'flags' corresponds to the processor status flags after executing the system call.
Regards,
- Patrick

User avatar
Rich Talbot-Watkins
Posts: 1592
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by Rich Talbot-Watkins » Tue Nov 12, 2019 12:57 pm

Richard Russell wrote:
Tue Nov 12, 2019 9:24 am
Simply an alternative to a comma, I think; not sure why semicolon is accepted here at all.
I think semicolon was the "standard" BASIC syntax for an INPUT command. Certainly MS BASIC expects a semicolon (comma is a syntax error).
That's a new one on me. I assume it's a RISC OS feature and if so it must have a very untypical ABI (returning multiple values is unusual enough, without the option of returning 'flags'). How does that map to a language like C which (as far as I'm aware) makes no such provision?
I don't know if RISC OS SWIs generally returned any kind of meaningful output in the flags, but one special case is of "X" SWIs, e.g. "XOS_File", which used the V flag to denote an error condition instead of actually generating an error.

User avatar
Richard Russell
Posts: 1246
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by Richard Russell » Tue Nov 12, 2019 1:53 pm

Rich Talbot-Watkins wrote:
Tue Nov 12, 2019 12:57 pm
I don't know if RISC OS SWIs generally returned any kind of meaningful output in the flags, but one special case is of "X" SWIs, e.g. "XOS_File", which used the V flag to denote an error condition instead of actually generating an error.
I know nothing about RISC OS, but I would have expected that any Operating System would ensure that its API functions can be called equally well from assembler code or from 'popular' high-level programming languages such as C. If you write an application in C and it needs to call the "XOS_File" function in RISC OS, how does the information get returned? Is it necessary to use some kind of assembly language 'wrapper' to achieve this?

User avatar
jgharston
Posts: 3927
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by jgharston » Tue Nov 12, 2019 6:45 pm

If you call an 'X' SWI it either returns with V clear and results in the registers, or returns with V set and R0 pointing to an error block.
SYS "XOS_File",5,filename$ TO result;flags:IF (flags AND 1) THEN result=>error block ELSE result=object type

If you call a non-X SWI it always returns with V clear, any error results in the error handler being invoked.
SYS "OS_File",5,filename$ TO result:result=object type, if an error occured, an error is generated

Some calls return information in the Carry flag, but that's deprecated, (almost) any state returned in the Carry flag is visible in the registers. For example:
SYS "OS_Byte",129,0,0 TO r0,r1;flags:IF (flags AND 2) THEN Escape occured
SYS "OS_Byte",129,0,0 TO r0,r1:IF r1=27 THEN Escape occured (r1=0 is ok, r1=&FF is timeout)

SYS "OS_GBPB",action,handle,address,count,pointer TO ;flags:IF (flags AND 2) THEN eof met
SYS "OS_GBPB",action,handle,address,count,pointer TO action,handle,address,count,pointer:IF count<>0 THEN eof met

I think the only call you can't seperate out the Carry flag is GET and BGET:
SYS "OS_BGET",handle TO byte;flags:IF (flags AND 2) THEN eof met
SYS "OS_RDCH" TO byte;flags:IF (flags AND 2) THEN Escape occured

The Modula-2, Pascal and C libraries wrap those calls to return -1 at Escape and -2 at EOF (in effect sign-extending the returned &FE to &FFFFFFFE).

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
jgharston
Posts: 3927
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by jgharston » Tue Nov 12, 2019 7:04 pm

If you write an application in C and it needs to call the "XOS_File" function in RISC OS, how does the information get returned? Is it necessary to use some kind of assembly language 'wrapper' to achieve this?
In general, most of the register information is passed in a block. Depending on the library,
CLib has _kernel_osfile(action, filename, controlblock) which returns -2 if an error occured, and you must call _kernel_last_oserror to find it, so you end up with contructions such as:

Code: Select all

if ((result=_kernel_osfile(5, filename, controlblock))==-2) {
  error=_kernel_last_oserror();
  do_something_with(error);
 } else {
  object=result;
  load=controlblock.load;
  exec=controlblock.exec;
}
RISCOS_Lib has os_file(fileblock) which returns 0 for Ok or a pointer to an error block if an error occured, so you end up with constructions such as:

Code: Select all

fileblock.action=5;
fileblock.pathname=filename;
if (result=os_file(fileblock)) {
  do_something_with(result);
 } else {
  object=fileblock.type;
  load=fileblock.load;
  exec=fileblock.exec;
}
I think there's a library that allows os_file(action,filename,load,exec,attrs). Thinking about it, it would have to pass load/exec/attrs by reference, so it's probably os_file(&action,filename,&load,&exec,&attrs) and probably returns 0=Ok, non-0=>error block.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
jgharston
Posts: 3927
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by jgharston » Tue Nov 12, 2019 7:44 pm

The _kernel calls give you more flexibility and are closer to the metal, but need more thinking to work out what you're doing. Quickly checking zZ80Tube I see I have:

Code: Select all

#ifdef Z80FILE_RO
ctrl.load =blah...
ctrl.exec =blah...
ctrl.start=blah...
ctrl.end  =blah...
chk_err(tmp=_kernel_osfile(Areg,filename,&ctrl));
Areg=tmp;
foo=ctrl.load;
foo=ctrl.exec;
foo=ctrl.start;
foo=ctrl.end;
#endif

Code: Select all

#ifdef Z80FILE_RO
/* Check if an error occured after calling RISC OS kernel		*/
int chk_err(int retval)
{
int l;

if (retval != -2) return FALSE;		/* No error			*/
oserr=*_kernel_last_oserror();		/* Find the error block		*/
blah....
return TRUE;
}
#endif

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
Richard Russell
Posts: 1246
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by Richard Russell » Tue Nov 12, 2019 7:52 pm

jgharston wrote:
Tue Nov 12, 2019 7:04 pm
Depending on the library...
I'm so glad that I work only with Operating Systems (Windows, Linux, MacOS, Android, iOS) in which BBC BASIC's SYS statement calls exactly the same API functions, in the same libraries, and with the same ABI, as a C program would. It makes life easier for a BASIC programmer, who can refer to the same API documentation as everybody else uses, and translating a C program to BBC BASIC can be trivial.

User avatar
Rich Talbot-Watkins
Posts: 1592
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by Rich Talbot-Watkins » Tue Nov 12, 2019 8:45 pm

The SWI system will always have needed some kind of macro wrapper around it in C, generating the correct instruction, because the SWI number was part of the opcode, rather than any kind of value set up in a register.

I think, when Acorn introduced the ARM6 or 7, which had a separate data and instruction cache, it was no longer efficient to handle SWIs in the old way, because it invariably involved having to load the SWI opcode, which would always cost a data cache load. I think later on there was a different way to handle SWI, although presumably RISC OS continued in the old way.

User avatar
jgharston
Posts: 3927
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: Uses of the semicolon in BBC BASIC

Post by jgharston » Wed Nov 13, 2019 8:50 am

Richard Russell wrote:
Tue Nov 12, 2019 7:52 pm
I'm so glad that I work only with Operating Systems (Windows, Linux, MacOS, Android, iOS) in which BBC BASIC's SYS statement calls exactly the same API functions, in the same libraries, and with the same ABI, as a C program would. It makes life easier for a BASIC programmer, who can refer to the same API documentation as everybody else uses, and translating a C program to BBC BASIC can be trivial.
On RISC OS, BBC BASIC's SYS call calls exactly the same API function as the C Library if you use the right library. Too many people threw together their own libraries to suit their own purposes, but there is/are libraries where BBC BASIC SYS "OS_File",a,b,c,d,e is C call os_file(&a,&b,&c,&d,&e), BASIC SYS "OS_GBPB",a,b,c,d,e is os_gbpb(&a,&b,&c,&d,&e), SYS "Wimp_Init",whatever is wimp_init(whatever). In general, the _kernel calls are exactly the same as the raw SWI calls, _kernel_swiname(list of register parameters) has the bare minimum ARM wrapper to transfer the parameters into registers and execute the SWI instruction. Something like
LDM (sp),r0-r4 ; get parameters into registers
SWI "OS_blah" ; do it
STM (sp),r0-r4 ; return registers into parameters
MOV link,pc ; return to caller

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

Post Reply

Return to “classic languages (e.g. BASIC) on non-acorn platforms”