Merge pull request #10 from gunyarakun/fix-invalid-return
[cocotron.git] / objc / objc_exception.m
blob06b1c465647c78afdcde17d833e3cc546302c90c
1 #import "objc_tls.h"
2 #import <stdio.h>
4 OBJC_EXPORT NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void);
5 OBJC_EXPORT void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *);
7 NSUncaughtExceptionHandler *NSThreadUncaughtExceptionHandler(void);
8 void NSThreadSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *function);
10 objc_exception_frame *NSThreadCurrentHandler(void) {
11     return objc_tlsCurrent()->exception_frame;
14 void NSThreadSetCurrentHandler(objc_exception_frame *handler) {
15     objc_tlsCurrent()->exception_frame = handler;
18 NSUncaughtExceptionHandler *NSThreadUncaughtExceptionHandler(void) {
19     return objc_tlsCurrent()->uncaught_exception_handler;
22 void NSThreadSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *function) {
23     objc_tlsCurrent()->uncaught_exception_handler = function;
26 void __NSPushExceptionFrame(objc_exception_frame *frame) {
27     frame->parent = NSThreadCurrentHandler();
28     frame->exception = nil;
30     NSThreadSetCurrentHandler(frame);
33 void __NSPopExceptionFrame(objc_exception_frame *frame) {
34     NSThreadSetCurrentHandler(frame->parent);
37 static void defaultHandler(id exception) {
38     __builtin_trap();
39     fprintf(stderr, "*** Uncaught exception\n");
40     // fprintf(stderr,"*** Uncaught exception <%s> *** %s\n",[[exception name] cString],[[exception reason] cString]);
43 void _NSRaiseException(id exception) {
44     objc_exception_frame *top = NSThreadCurrentHandler();
46     if(top == NULL) {
47         NSUncaughtExceptionHandler *proc = NSGetUncaughtExceptionHandler();
49         if(proc == NULL)
50             defaultHandler(exception);
51         else
52             proc(exception);
53     } else {
54         NSThreadSetCurrentHandler(top->parent);
56         top->exception = exception;
58         longjmp(top->state, 1);
59     }
62 // Enable that to put back original Cocotron behaviour, where every thread has its own default
63 // uncaught handler
64 //#define PER_THREAD_UNHANDLED_EXCEPTION_HANDLER
66 #ifdef PER_THREAD_UNHANDLED_EXCEPTION_HANDLER
68 NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void) {
69     return NSThreadUncaughtExceptionHandler();
72 void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *proc) {
73     NSThreadSetUncaughtExceptionHandler(proc);
75 #else
76 static NSUncaughtExceptionHandler *uncaughtExceptionHandler = NULL;
78 NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void) {
79     return uncaughtExceptionHandler;
82 void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *proc) {
83     uncaughtExceptionHandler = proc;
85 #endif
87 #if !defined(GCC_RUNTIME_3) && !defined(APPLE_RUNTIME_4)
89 void __gnu_objc_personality_sj0() {
90     printf("shouldn't get here\n");
91     abort();
94 void objc_exception_try_enter(void *exceptionFrame) {
95     __NSPushExceptionFrame((objc_exception_frame *)exceptionFrame);
98 void objc_exception_try_exit(void *exceptionFrame) {
99     __NSPopExceptionFrame((objc_exception_frame *)exceptionFrame);
102 id objc_exception_extract(void *exceptionFrame) {
103     objc_exception_frame *frame = (objc_exception_frame *)exceptionFrame;
104     return (id)frame->exception;
107 void objc_exception_throw(id exception) {
108     _NSRaiseException(exception);
109     abort();
112 static BOOL isKindOfClass(id object, Class kindOf) {
113     Class class = object_getClass(object);
115     while(object_getClass((id)object_getClass((id) class)) != class) {
117         if(kindOf == class) {
118             return YES;
119         }
121         class = class_getSuperclass(class);
122     }
124     return NO;
127 int objc_exception_match(Class exceptionClass, id exception) {
128     return isKindOfClass(exception, exceptionClass);
131 #endif