RISCOS.com

www.riscos.com Technical Support:
Programmer's Reference Manual

 

Generating and handling errors


Introduction

It is reasonable to expect that most SWIs can generate an error. For example, if you pass poor parameters you would expect the SWI routine to tell you about it.

SWIs report errors in a consistent way. If no error occurred, and the desired action was performed, the SWI routine will clear the ARM's V (overflow) flag on exit. If an error did occur, the SWI routine will set V on exit. Furthermore, R0 will contain a pointer to an error block, which is described below.

Error handling

Just before RISC OS passes control back to your program, it checks the V flag. If it is clear (no error occurred) control passes directly back.

If V is set (an error occurred), RISC OS looks at a copy of the original SWI instruction you used:

  • If you had cleared bit 17 of the SWI number, RISC OS deals with the error itself. Control does not return normally to your program; instead the error is passed to the error handler used by your program, which normally will report the error to you.
  • If you had set bit 17 of the SWI number, RISC OS returns control directly to your program. The V flag will still be set to indicate an error, and R0 will contain the error pointer. It is up to you to deal with the error.
Types of SWIs

These two types of SWI are known respectively as error-generating and error-returning SWIs. For every SWI, you can call either version, depending on whether you want to detect the error yourself, or leave the current error handler to deal with it. All the examples in the chapter * Commands and the CLI were error-generating SWIs. If you want to call an error-returning SWI, with bit 17 set:

  • add &20000 to the SWI number you use; or:
  • put the letter X in front of the SWI name, thus:
    XOS_WriteC, XWimp_OpenWindow, and so on.

Error blocks

The error block pointed to by R0 has the following format:

    R0 + 0 a word containing the error number
    R0 + 4 error message, terminated by a zero byte.

An error block must be word-aligned, and must be no more than 256 bytes long.

Error numbers

Just as the 24-bit SWI number is divided into different fields, 32-bit error numbers are also split up.

The bottom byte is often a basic 'error number'.

The middle two bytes identify what generated the error. Third parties generating their own errors must apply to Acorn for an identifier. The following error ranges have been reserved:

Range Error generator
&000 - &0FF Operating system - BBC-compatible error
&100 - &11F OS_Module errors
&120 - &13F OS_ReadVarVal/SetVarVal errors
&140 - &15F Redirection manager errors
&160 - &17F OS_EvaluateExpression errors
&180 - &19F OS_Heap errors
&1A0 - &1AF OS_Claim/Release errors
&1B0 - &1BF OS_ChangeEnvironment errors
&1C0 - &1DF OS_ChangeDynamicArea errors
&1E0 - &1EF OS_CLI/miscellaneous errors
&200 - &27F Font manager errors
&280 - &2BF Wimp errors
&2C0 - &2FF Date/time conversion errors
&300 - &3FF Econet errors
&400 - &4FF FileSwitch errors
&500 - &5BF Podule errors
&5C0 - &5FF Printer driver errors
&600 - &63F General OS errors
&640 - &6FF International module errors
&700 - &7FF Sprite errors
&800 - &87F Debugger errors
&880 - &8FF BBC I/O Podule errors
&900 - &97F Shell CLI errors, and miscellaneous others
&980 - &9FF Draw errors
&A00 - &A3F ColourTrans errors
&A40 - &A7F ARM3 errors
&A80 - &ABF TaskWindow errors
&AC0 - &AFF MessageTrans errors
&B00 - &B3F Pinboard errors
&B40 - &B4F Portable module errors
&1XX00 - &1XXFF Errors from filing system number &XX
(eg &10800 - &108FF ADFS errors)
&20000 - &200FF Sound errors
&20200 - &21000 Podule errors, and miscellaneous others

The top byte contains flags:

  • Bit 31, if set, implies that the error was a serious one, usually a hardware exception (eg the program tried to access non-existent memory) or floating point exception, from which it wasn't possible to sensibly return with V set. In such cases different error ranges are used:
    &80000000 - &800000FF Machine exceptions
    &80000100 - &800001FF CoProcessor exceptions
    &80000200 - &800002FF Floating Point exceptions
    &80000300 - &800003FF Econet exceptions
  • Bit 30 is defined to be clear, and can therefore be used by programmers to flag internal errors.
  • Bits 24 - 29 are reserved. They should be cleared for compatibility with any future extensions.

Technical details of error-generating SWIs

You may need to know in more detail how RISC OS handles an error that an error-generating SWI creates.

  1. First it informs modules of the error using the SWI OS_ServiceCall, with reason code 6 (Error). This is for the module's information only, so that it can tidy up (close files, and so on) before RISC OS handles the error. The module must not try to handle the error.
  2. It then calls the error vector (for a detailed description see the chapter entitled ErrorV). By default, this calls the current error handler. You may claim this vector, but again this should be for information only - for example, so that your program can tidy up. The call must subsequently be passed on to the error handler; your program must not try to handle the error.

If you want to handle an error yourself, you must instead use the error-returning version of the SWI.

Generating errors

In addition to detecting errors, you might want to generate an error which calls the current error handler, so you can find out about a problem. A common example would be if you detect that Esc is pressed. This is usually a sure sign that the user wants to abandon the current operation. The standard response is for you to acknowledge the escape (see the chapter entitled Character Input for details), and generate an 'Escape' error. This is then dealt with by the current error handler.

To generate the error, you should call the SWI OS_GenerateError. On entry, R0 contains a standard error block pointer. The routine never returns. For example, BASIC's error handler will cause the current BASIC program to terminate, returning control to the command mode, or to execute an ON ERROR statement, if one is active.

Writing system extension code

You must not write system extension code (such as a module, interrupt handler or transient) that generates errors - users of this code have a right to expect it to work. This means that you must always use the X form of SWIs in such code.

The only time you should call OS_GenerateError from system extension code is to report exception-type errors - that is, when bit 31 of the error number is set. For example, the Floating Point Emulator uses this mechanism to report exceptions from both the hardware and software floating point processors, as coprocessor instructions obviously cannot return with the V bit of the ARM processor set to indicate an error.

SWI Calls


OS_GenerateError
(SWI &2B)

Generates an error and invokes the error handler

On entry

R0 = pointer to error block

On exit

Doesn't return - OS_GenerateError (SWI &2B) or
V flag is set - XOS_GenerateError (SWI &2002B)

Interrupts

Interrupts are enabled by OS_GenerateError, but unaltered by the X form
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

OS_GenerateError generates an error and invokes the error handler. Whether or not it returns depends on the type of SWI being used. If XOS_GenerateError is used, the only effect is to set the V flag. This is not very useful.

Here is an example of how OS_GenerateError would be used:

   SWI   "OS_ReadEscapeState"        ; Sets C if escape
   BLCS  acknowledge_escape          ; acknowledge it - returns using
                                     ; LDMFD R13!,{PC}^
   ADRCS R0,escapeBlock              ; Get ptr. to error block
   MOVCS R1,#0                       ; Use global messages file
   MOVCS R2,#0                       ; Use internal buffer
   SWICS "XMessageTrans_ErrorLookup" ; Look up token in message file
   SWICS "OS_GenerateError"          ; Do the error - doesn't return
.noEscape
   ...
.escapeBlock
   EQUD  17                          ; Error number for escape
   EQUS  "Escape"+CHR$0              ; Error token to lookup
   ALIGN
Related SWIs

None

Related vectors

ErrorV

* Commands


*Error

Generates errors

Syntax
*Error [error_no] text
Parameters
error_no the error number
text a string of printable characters explaining the error
Use

*Error generates an error with the given error number and explanatory text. This is normally then printed on the screen. This command is useful for reporting errors after trapping them within a command script.

If you omit the error number it is set to the default value of 0.

Errors are also, of course, generated by RISC OS itself.

Example

*Error 100 No such file prints 'No such file'

Related commands

None

Related SWIs

OS_GenerateError (SWI &2B)

Related vectors

ErrorV

This edition Copyright © 3QD Developments Ltd 2015
Last Edit: Tue,03 Nov 2015