/* Catch.m * * Copyright Niels Möller 1995 * * Freely distributable under the terms and conditions of the * GNU General Public License. */ #include #include #include #define CANT_HAPPEN assert(1) /* I'm not sure if I should hardcode StackFrame here or not. */ #ifndef FRAME_STACK #define FRAME_STACK [self class] #endif FRAME_STACK @implementation Catch_common - (JMP_BUF *) where { return &where; } - (JMP_BUF *) catch; { if (frame) [self cleanup]; frame = [FRAME_STACK pushCatch: self]; return [self where]; } - (void) jump { LONGJMP(*[self where], 42); } @end /* Catch_common */ @implementation Catch - value { return result; } - value: newValue { result = newValue; return self; } - (BOOL) matches: tag { return [tag isEqual: self]; } - (void) throw: value { [self throw: value free: YES]; } - (void) throw: value free: (BOOL) freeFlag { frame_id fr; id catch; fr = [FRAME_STACK findFrameMatching: self]; if (fr) { catch = ( (struct frstack_catch_object_frame *) fr)->object; [catch value: value]; /* If freeFlag is true, and we are not the same object as the one * used in the catch, free. */ if (freeFlag && !(catch == self)) [self free]; [FRAME_STACK unwind: fr pleaseReturn: NO]; CANT_HAPPEN; } /* No matching catch found. Try signalling an error. */ [[[[ThrowWithoutCatch new] value: value] tag: self] raise]; CANT_HAPPEN; } @end /* Catch */ @implementation CatchException - exceptionType { return exceptionType; } - exceptionType: type { exceptionType = type; return self; } - exception { return result; } - exception: object { result = object; return self; } - (JMP_BUF *) catch: type { return [ [self exceptionType: type] catch]; } - (BOOL) matches: tag { return [tag conformsTo: @protocol(AnyException)] && [tag ofExceptionType: exceptionType]; } - free { if (result) [result finished]; return [super free]; } @end /* CatchException */