C for Yourself - part 18

Steve Mumford investigates performing SWI calls from within C.

Welcome to the start of a new phrase in Acorn User's monthly C tutorial - now we've covered the basics of programming an application in C, it's time to add the various mechanisms needed to allow the code to multitask in Acorn's desktop. However, it's not a particularly simple task and last month, I briefly mentioned the various libraries supplied with the compilers on the market. These aim to make the programmer's life a little easier by supplying ready-made C functions to automate the processes necessary to maintain a WIMP application.

Due to the problems associated with picking out a single library for the tutorial and disappointing those who don't have it, I've decided to take a lower level approach and attempt to build up our own library, using Acorn's SWI calls to control the WIMP directly. In this way, I hope to be able to introduce you to the methods of building your own libraries, as well as programming the WIMP. Since SWI calls are available in other languages available for the Acorn, the topics I'll cover in the forthcoming months should be applicable to a wide range of readers. From time to time, I'll compare the techniques I'm using with the libraries available so you'll be able to see the differences between them.

This month, I intend to cover the basics of calling a SWI from within a C program, giving you access to a wide range of utilities. Although we're not going to be building up a WIMP application just yet, we need to cover the SWI mechanisms now so that we can use the relevant WIMP calls in the future.

However, once you've mastered the techniques given below, you'll be able to inject your single-tasking applications with a bit more power. Of course, as soon as you start using SWI calls, your program is no longer portable - but that's a small price to pay.

In order to access these functions, we'll have to #include two new header files which we haven't made use of before. These are kernel.h and swis.h, and versions of these are supplied with both Beebug's Easy C and Acorn's C package.

The first of these provides the definitions of the functions we'll be using to call the SWIs, along with some important structure definitions which are used to hold the register information passed to and from the SWI.

The second file contains a long list of #define commands, allowing the programmer to use the textual variants of the SWI names and avoiding the need to remember those eminently forgettable hexadecimal numbers.

I've included a basic demonstration of a SWI call on the cover disc, compiled by both Acorn and Beebug compilers - it simply performs an OS_Mouse system call and prints up the coordinates it returns whenever a mouse button is pressed. Before calling a SWI, there are a few data structures that you need to set up. Firstly, since you know how little error-trapping C does by itself, it's important to have a device to catch calls that produce errant results. To this end, a structure has been defined in kernel.h capable of holding an error number and message:

typedef struct
  int errnum;
  char errmess[252];
} _kernel_oserror;

Once you've included kernel.h, you don't need to re-define this structure, and all you're required to do is declare a structure of your own with the line similar to the one below:

_kernel_oserror error;

The function itself takes three parameters - an integer giving the SWI number, and two structures each containing an array of ten integers. These hold the register values passed to and from the SWI command, and are set up prior to the call.

_kernel_swi_regs in;
_kernel_swi_regs out;

I've not needed to initialise in.r[] because OS_Mouse doesn't take any register input - it just passes values back in registers 0 to 4. We call the SWI as follows, typing in the full name instead of the number since this will be replaced by the appropriate swis.h definition on compilation.

error = *_kernel_swi(OS_Mouse, &in, &out);

On this occasion, I haven't implemented any error checking, but I've shown you the general form because it'll crop up a number of times in the future. The parameters are retrieved by standard structure manipulation, and they're printed using printf(). That's all there is to it - well, for now at least. See you next time.

Source: Acorn User - 162 - December 1995
Publication: Acorn User
Contributor: Steve Mumford