Exception
ClassException
and its subclasses handle system and language
errors. These classes provide default and
user-defined handlers to respond to the Exceptions;
If a program calls enableExceptionTrace
(class Object
),
then the handle
method, below, and other exception handlers
print a walkback of the program’s method stack. See Object.
Here is an example of how to handle an exception when trying to open a file.
Exception new e; ... e enableExceptionTrace; ... inputStream openOn fileArg; if (e pending) { e handle; exit (1); }
The pending
method returns TRUE
or FALSE
depending on whether an exception is waiting to be
processed. The handle
method processes the exception.
The class’s default method handlers format and print the
text provided when a program calls raiseException
.
Here is the code from openOn
(class
ReadFileStream
) that creates the exception.
SystemErrnoException new e; ... if ((f = fopen (__streamPath, "r")) != NULL) { __ctalkObjValPtr (selfval, f); self streamPath = __streamPath; self statStream; } else { e raiseCriticalException __streamPath; strcpy (selfval -> __o_value, ""); }
The object e
is a SystemErrnoException
. The
SystemErrnoException
class translates the operating
system’s errors into Ctalk exceptions. In the example
above, the type of the exception is provided by the
operating system.
The Exception
class also provides the
installHandler
method to allow programs to use their
own handlers. Here is an example.
Exception instanceMethod myHandler (void) { printf ("My exception handler: %s.\n", __ctalkGetRunTimeException ()); return NULL; } int main () { Exception new e; e installHandler "myHandler"; e raiseException USER_EXCEPTION_X, "my program's exception"; e handle; }
1. The receiver class of an exception handler is the the
same as the exception object; e.g., myHandler
in the
example above is the same as the class of e
; that is,
Exception
. In addition, exception handlers take no
arguments and rely on information at the time the exception
is raised.
2. Programs must take care that they handle any exceptions that they raise as soon as possible. If not handled by the application, the run-time library API might then handle the exception, which could lead to confusing results.
3. Ctalk uses critical exceptions internally. At the application level, however, all exceptions are treated with the same priority. The application needs to take the appropriate action, depending on the type of exception.
4. Exception classes should not, as much as possible, depend
on other classes being evaluated. This is because even
basic classes use exceptions, and if the exceptions in turn
use the basic classes, it can lead to circular reference.
In fact, Symbol
is one of the few classes that
Exception
can use without generating circular method
and class references. That is why the handlerMethod
instance variable (see below) is implmented as a
Symbol
.
5. When writing exception handlers, you should use as much
as possible the following library API functions:
__ctalkGetRunTimeException, __ctalkHandleRunTimeException,
__ctalkPeekRunTimeException, __ctalkPeekExceptionTrace, and
__ctalkPendingException. They are located in
lib/except.c
and described in a later
section. See Ctalk library.
6. The only way to distinguish between different exceptions within a handler is to compare the text returned by a function like __ctalkGetRunTimeException. The exception information is generated at the time the exception is raised, which is the information that the program should be interested in. Handling exceptions as soon as possible also helps avoid confusion if one exception then causes other exceptions. Also, different operating systems map errors codes differently, so Ctalk uses the operating systems’ interpretations of the errors.
7. Exception handlers in calling methods take priority over handlers in the methods they call. You need to be careful that exception handlers within the scope of a caller do not supercede each other. This is especially true if an application tries to use a global Exception object. You should try to keep Exception objects as local as possible.
Exceptions have a corresponding integer code. The following macros correspond to the actual exceptions.
SUCCESS_X CPLUSPLUS_HEADER_X MISMATCHED_PAREN_X FALSE_ASSERTION_X FILE_IS_DIRECTORY_X FILE_ALREADY_OPEN_X UNDEFINED_PARAM_CLASS_X PARSE_ERROR_X INVALID_OPERAND_X PTR_CONVERSION_X UNDEFINED_CLASS_X UNDEFINED_METHOD_X METHOD_USED_BEFORE_DEFINE_X SELF_WITHOUT_RECEIVER_X UNDEFINED_LABEL_X UNDEFINED_TYPE_X UNDEFINED_RECEIVER_X UNKNOWN_FILE_MODE_X INVALID_VARIABLE_DECLARATION_X WRONG_NUMBER_OF_ARGUMENTS_X SIGNAL_EVENT_X INVALID_RECEIVER_X NOT_A_TTY_X USER_EXCEPTION_X
handlerMethod
A Symbol
object that contains the address of a
user defined method to handle exceptions.
deleteLastException (void
)
Delete the last generated exception from Ctalk’s internal exception list.
handle (void
)
Execute the exception handler for the next pending method.
If a program calls enableExceptionTrace
(class Object
),
then handle
also displays a walkback of the exception’s copy of
the program call stack. See Object.
exceptionHandler
(void
)
Handle an exception either with Ctalk’s default exception
handler or a user defined handler. If the program has
called the traceEnabled
method (class Object
),
print a stack trace also.
installHandler
(char *
handler_method_name)
Install a user-defined method to handle exceptions. The
method’s receiver class must be of the same class as the exception; i.e.,
either Exception
or SystemErrnoException
.
peek (void
)
Returns a String
containing the text of the first pending
exception, if any.
pending (void
)
Return TRUE
if any exceptions are pending, FALSE
otherwise.
raiseCriticalException (EXCEPTION
ex, char *
text)
Raise a critical exception. A critical exception is similar to a
normal exception, below, except that it is not caught internally. The
application must catch the exception with pending
and handle.
You should use one of the EXCEPTION
macros defined above
as the argument ex.
Print a trace of the methods in the current exception’s copy of the program’s call stack.
raiseException (EXCEPTION
ex, char *
text)
Raise an exception. You should use one of the EXCEPTION
macros
defined above as the argument ex.