Ruby816 – BCPL Issues and the importance of testing

Just a short post to briefly mention some bring-up issues for BCPL and maybe applicable to software testing in general…

The main one is the filing system – I initially developed this for the Ruby 6502 board. It runs on the host processor (ATmega 1284p) and is written in C. I boringly call it RuFs for Ruby Filing System.

It’s based loosely on Apple ProDOS with similar limitations. A maximum disk size of 32MB (which is fine), however I changed some other limitations – a directory can be many blocks long (so essentially unlimited number of files in each directory), and I wanted longer filenames, so doing some calculations, I settled on a maximum filename length of 21 characters. The directory entry for each file also needed to include some additional fields to cater for the Acorn/BBC Micro file attributes, although the filesystem itself presents a fairly common “Posixy” style interface of open/read/write/close. There is a translation layer in the 6502/65816 side to allow Acorn MOS style osFile, osFind, etc. system calls to work from BBC BASIC.

My C library (for cc65) bypasses RubyOS as does the BCPL “device” IO library (and more on that later).

I’ve been using it for some time and it was working well, although I’ve only (somewhat lazily) only implemented what I needed to use, so while it supports sub directories, and I can ‘mkdir’, I’ve not written code to actually ‘chdir’ as yet.

Enter the BCPL compiler… I developed the device IO library and enough of the BCPL streams IO library to make simple file handling work. (RuFs doesn’t support seek yet) I was compiling BCPL programs on my Linux desktop and copying them over to the board to run, but my aim was to compile directly on Ruby, so when I felt the cintcode interpreter was good enough, I copied the compiler over and ran it. Initially it fell upon many more unimplemented cintcode instructions so these were written until eventually the compiler worked. (There was another issue with the way BCPL programs take command-line arguments, again more on this later).

But it did work and I compiled a simple “Hello, World!” program. Encouraged by this, I set about compiling a bigger program – the Mandelbrot test program. It failed somewhat spectacularly. It produced an output file some 256KB in size which was obviously bogus, but now I had a lot of testing to do. The unlimited digits of Pi program also failed.

To cut a long story short, the issue turned out to be in my filing system – there was some data accidentally shared between open file “handles”. I’d never noticed it before because I’d never had one file open for reading with a 2nd file open for writing, but that’s what the BCPL compiler does – and the shared data only rears it’s head when the file I’m reading is more than one disk/sd block – so files less than 512 bytes in size (e.g. hello.b and some other trivial tests I was using) were fine, but bigger files would trigger this bug.

Once I fixed it – and tested it – I was able to compile bigger programs. This has shown up other issues, but not bugs – one being just how relatively slow the compiler is when reading text files in – with the “libhdr.h” file (BCPL equivalent of <stdio.h>) being 20KB long taking longer to read than the actual program, but I can work on that.