.\" -*-nroff-*- .de VS .sp 1 .in +5n .ft B .nf .. .de VE .ft R .in -5n .sp 1 .fi .. .TH exc 3 "20 June 1999" "Straylight/Edgeware" "mLib utilities library" .SH NAME exc \- exception handling for C programs .\" @TRY .\" @CATCH .\" @END_TRY .\" @THROW .\" @RETHROW .\" .\" @exc_uncaught .\" .\" @EXC_PAIR .\" @EXC_ALLOC .\" @EXC_ALLOCN .\" @EXC_ALLOCI .\" @EXC_ALLOCP .\" @EXC_ALLOCS .\" .SH SYNOPSIS .B "#include " .sp 1 .B TRY .I statement .B CATCH .I statement .B END_TRY; .br .B EXIT_TRY; .sp 1 .BI "THROW(exc_extype " type .RB [ , .IR data ]\fB); .br .B RETHROW; .sp 1 .nf .B "typedef void (*exc__uncaught)(exc_extype, exc_exval);" .BI "exc__uncaught exc_uncaught(exc__uncaught " proc ); .BI "exc_extype EXC_PAIR(unsigned char " x ", unsigned char " y ); .BI "exc_extype EXC_ALLOC(exc_extype " owner ", exc_extype " type ); .BI "exc_extype EXC_ALLOCN(exc_extype " owner ", exc_extype " type ); .BI "exc_extype EXC_ALLOCI(exc_extype " owner ", exc_extype " type ); .BI "exc_extype EXC_ALLOCP(exc_extype " owner ", exc_extype " type ); .BI "exc_extype EXC_ALLOCS(exc_extype " owner ", exc_extype " type ); .fi .SH DESCRIPTION The header file .B introduces some new syntax and definitions to support exception handling in C. The marriage is not particularly successful, although it works well enough in practice. .PP The syntax introduced consists of new .B TRY and .B EXIT_TRY statements and a pair of new expression types .B THROW and .BR RETHROW . It's unfortunately important to remember that the syntax is provided using macro expansion and standard C facilities; some of the restrictions of these features show through. .SS "The TRY statement" The .B TRY statement associates an exception handler with a piece of code. The second statement is an .IR "exception handler" . Its .I "dynamic scope" is the duration of the first statement's execution, together with the duration of any functions called within the dynamic scope. (Note in particular that an exception handler is not within its own dynamic scope.) A thrown exception causes the exception handler with dynamically innermost scope to be executed. .PP Two special variables are provided to the exception handler: .TP .B exc_type The .I type of the exception caught. This is value of type .B exc_extype (described below). .TP .B exc_val The .I value of the exception. This has a union type, with members .BR "int i", .B "void *p" and .BR "char *s" . Only one of the members is valid; you should be able to work out which from the exception type. There are abbreviations .BR "exc_i", .B exc_p and .B exc_s which refer to members of .B exc_val directly. .SS "The EXIT_TRY statement" It is not safe to leave the dynamic scope of an exception handler early (e.g., by a .B goto statement). You can force a safe exit from a dynamic scope using the .B EXIT_TRY statement from within the .I lexical scope of the .B TRY statement. .SS "The THROW and RETHROW statements" The .B THROW expression throws an exception. The first argument is the type of exception; the second is some data to attach to the exception. The type of data, integer, string or pointer, is determined from the exception type. .PP Control is immediately passed to the exception handler with the innermost enclosing dynamic scope. .PP The .B RETHROW expression is only valid within an exception handler. It rethrows the last exception caught by the handler. .PP Neither .B THROW nor .B RETHROW yields any value. .SS "Exception type allocation" Exception types are 32-bit values. The top 16 bits are an .IR "owner identifier" . The idea is that each library can have an owner identifier, and it can then allocate exceptions for its own use from the remaining space. Two special owner codes are defined: .TP .B "EXC_GLOBAL (0x0000)" The global space defined for everyone's benefit. Don't define your own exceptions in this space. .TP .B "EXC_SHARED (0xffff)" A shared space. You can use this for any exceptions which won't be seen by anyone else. .PP Other owner codes may be allocated by choosing two characters (probably letters) which best suit your application and applying the .B EXC_PAIR macro to them. For example, the owner code for .B mLib would probably be .BR "EXC_PAIR('m', 'L')" , if .B mLib defined any exceptions other then the global ones. .PP The bottom 16 bits are the actual exception type, and the data type which gets passed around with the exception. The data type is (bizarrely) in bits 6 and 7 of the type word. The data type code is one of the following: .TP .B EXC_NOVAL There is no data associated with this exception. .TP .B EXC_INTVAL The data is an integer, with type .BR int . .TP .B EXC_PTRVAL The data is a pointer to some data structure, with type .BR "void *" . Note that you probably have to do an explicit cast to .B "void *" in the .B THROW expression. .TP .B EXC_STRVAL The data is a pointer to a string of characters, of type .BR "char *" . .PP If the data to be thrown is a pointer, make sure that the object pointed to has a long enough lifetime for it to actually get to its exception handler intact. In particular, don't pass pointers to automatic variables unless you're .I sure they were allocated outside the handler's dynamic scope. .PP Individual exceptions are allocated by the macros .BI EXC_ALLOC t\fR, where .I t is one of: .TP .B N The exception has no data .TP .B I The exception data is an integer. .TP .B P The exception data is a pointer. .TP .B S The exception data is a character string. .PP The .BI EXC_ALLOC t macros take two arguments: the owner code (usually allocated with .B EXC_PAIR as described above), and the type code. The data type is encoded into the exception type by the allocation macro. .SS "Predefined exceptions" The following exceptions are predefined: .TP .B EXC_NOMEM No data. Signals an out-of-memory condition. .TP .B EXC_ERRNO Integer data. Signals an operating system error. The data is the value of .B errno associated with the error. .TP .B EXC_OSERROR Pointer data. Signals a RISC\ OS error. The data is a pointer to the RISC\ OS error block. (Non RISC\ OS programmers don't need to worry about this.) .TP .B EXC_SIGNAL Integer data. Signals a raised operating system signal. The data is the signal number. .TP .B EXC_FAIL String data. Signals a miscellaneous failure. The data is a pointer to an explanatory string. .SH BUGS The call to an exception handler is achieved using .BR longjmp (3). Therefore all the caveats about .B longjmp and automatic data apply. Also, note that status such as the signal mask is not reset, so you might have to do that manually in order to recover from a signal. .SH "SEE ALSO" .BR mLib (3). .SH AUTHOR Mark Wooding,