home *** CD-ROM | disk | FTP | other *** search
- /*
- * ObjectError
- *
- * You may freely copy, distribute and reuse the code in this example.
- * This code is provided AS IS without warranty of any kind, expressed
- * or implied, as to its fitness for any particular use.
- *
- * Copyright 1995 Ralph Zazula (rzazula@next.com). All Rights Reserved.
- *
- * Based on the original ObjectError by Julie Zelenski
- *
- */
-
- #import "ObjectError.h"
- #import <appkit/nextstd.h>
- #import <sys/signal.h>
- #import <strings.h>
- #import <stdio.h>
-
- typedef struct _sig {
- int number;
- BOOL isOn;
- char *message;
- } SignalItem;
-
- typedef struct _type {
- char encoding;
- char *format;
- char *name;
- } ObjcType;
-
- extern SignalItem signals[];
- extern ObjcType encodings[];
-
- @implementation ObjectError
-
- static void handle_signal (int signal);
- static BOOL ignoreCrashes;
-
- + setup
- {
- [self poseAs:[Object class]];
- [self setSignalHandler:handle_signal];
- ignoreCrashes = NO;
- return self;
- }
-
- + setSignalHandler:(void(*)())handler
- {
- SignalItem *cur;
-
- for(cur = signals; cur->number; cur++) {
- if(cur->isOn) {
- signal(cur->number, handler);
- }
- }
- return self;
- }
-
- + resumeHandlingCrashes
- {
- [self setSignalHandler:handle_signal];
- ignoreCrashes = NO;
- return self;
- }
-
- + stopHandlingCrashes
- {
- [[self class] setSignalHandler:(void (*)())SIG_DFL];
- ignoreCrashes = YES;
- return self;
- }
-
- #define MAX_FUNCTION_ARGS 4
-
- + printFunctionFromFP:(void *)framePointer
- {
- char buffer[256];
- char line[1024];
- void *argStart;
- long argNum;
-
- sprintf(line, "function (");
- argStart = framePointer + 8;
- for(argNum = 0; argNum < MAX_FUNCTION_ARGS; argNum++) {
- sprintf(buffer, "%s0x%06lx", (argNum != 0 ? ", " : ""),
- *(((long *)argStart) + argNum));
- strcat(line, buffer);
- }
- strcat(line, ")");
- NXLogError("%s\n",line);
- return self;
- }
-
- #define IS_CLASS(object) ([object class] == object)
-
- + printMethodFromFP:(void *)framePointer
- {
- char buffer[256];
- char line[1024];
- SEL selector;
- id object;
- Method m;
- BOOL isClassMethod;
-
- object = *(id *)(framePointer + 8);
- selector = *(SEL *)(framePointer + 12);
- isClassMethod = IS_CLASS(object);
-
- sprintf(line, "%c[%s %s",(isClassMethod ? '+' : '-'),
- object_getClassName(object), sel_getName(selector));
-
- m = (isClassMethod ? class_getClassMethod([object class], selector) :
- class_getInstanceMethod([object class], selector));
-
- if(m) {
- void *argStart = (framePointer + 8);
- int argNum, numArgs, offset;
- char *type;
-
- numArgs = method_getNumberOfArguments(m);
- argNum = 2;
- while(argNum < numArgs) {
- ObjcType *cur;
-
- method_getArgumentInfo(m, argNum, &type, &offset);
- for(cur = encodings; cur->encoding; cur++) {
- if(cur->encoding == type[0]) {
- sprintf(buffer, " :(%s)", cur->name);
- strcat(line,buffer);
- sprintf(buffer,cur->format,*(long*)(argStart+offset));
- strcat(line,buffer);
- break;
- }
- }
- argNum++;
- }
- } else {
- strcat(line, " Unknown Method");
- }
- strcat(line, "]");
- NXLogError("%s\n",line);
- return self;
- }
-
- #define MAX_FRAMES 50
-
- + printBacktrace
- {
- void *framePointer;
- unsigned int frameCount;
-
- [self stopHandlingCrashes];
-
- #if DEBUG
- framePointer = ((void *) &self) - 8;
- frameCount = 0;
-
- while(frameCount < MAX_FRAMES && framePointer) {
- if(sel_isMapped(*(SEL *)(framePointer + 12))) {
- [self printMethodFromFP:framePointer];
- } else {
- [self printFunctionFromFP:framePointer];
- }
-
- framePointer = (void *)*(long *)framePointer;
- }
- #endif
-
- return self;
- }
-
- + dumpBacktrace:(const char *)message
- {
- NXLogError("%s: %s\n", [self name], message);
- [self printBacktrace];
- return self;
- }
-
- static void handle_signal(int signal)
- {
- const char *msg = NULL;
- char buf[256];
- SignalItem *cur;
-
- msg = "Unrecognized signal";
- for(cur = signals; cur->number; cur++) {
- if(cur->number == signal) {
- msg = cur->message;
- break;
- }
- }
- sprintf(buf, "Caught signal #%d: \"%s\"",signal, msg);
- [ObjectError dumpBacktrace:buf];
- }
-
- - error:(const char *)aString, ...;
- {
- va_list ap;
- char buffer[1024];
-
- va_start(ap, aString);
- vsprintf(buffer, aString, ap);
- va_end(ap);
- if(!ignoreCrashes) {
- [[self class] dumpBacktrace:buffer];
- [[self class] resumeHandlingCrashes];
- } else {
- return [super error:buffer];
- }
- return self;
- }
-
- + error:(const char *)aString, ...;
- {
- va_list ap;
- char buffer[1024];
-
- va_start(ap, aString);
- vsprintf(buffer, aString, ap);
- va_end(ap);
- if(!ignoreCrashes) {
- [[self class] dumpBacktrace:buffer];
- [[self class] resumeHandlingCrashes];
- } else {
- return [super error:buffer];
- }
- return self;
- }
-
- #define ON 1
- #define OFF 0
-
- SignalItem signals[] = {
- { SIGHUP , OFF, "hangup"},
- { SIGINT , OFF, "interrupt"},
- { SIGQUIT , ON, "quit"},
- { SIGILL , ON, "illegal instruction"},
- { SIGTRAP , ON, "trace trap"},
- { SIGIOT , ON, "IOT instruction"},
- { SIGEMT , ON, "EMT instruction"},
- { SIGFPE , ON, "floating point exception"},
- { SIGKILL , OFF, "kill"},
- { SIGBUS , ON, "bus error"},
- { SIGSEGV , ON, "segmentation violation"},
- { SIGSYS , ON, "bad argument to system call"},
- { SIGPIPE , OFF, "write on pipe with no reader"},
- { SIGALRM , OFF, "alarm clock"},
- { SIGTERM , OFF, "software termination"},
- { SIGURG , OFF, "urgent condition present on socket"},
- { SIGSTOP , OFF, "stop"},
- { SIGTSTP , OFF, "stop signal generated from keyboard"},
- { SIGCONT , OFF, "continue after stop"},
- { SIGCHLD , OFF, "child status has changed"},
- { SIGTTIN , OFF, "background read attempted from control terminal"},
- { SIGTTOU , OFF, "background write attempted to control terminal"},
- { SIGIO , OFF, "i/o is impossible on descriptor"},
- { SIGXCPU , OFF, "cpu time limit exceeded"},
- { SIGXFSZ , OFF, "file size limit exceeded"},
- { SIGVTALRM , OFF, "virtual time alarm"},
- { SIGPROF , OFF, "profiling timer alarm"},
- { SIGWINCH , OFF, "window size changed"},
- { SIGUSR1 , OFF, "user defined #1"},
- { SIGUSR2 , OFF, "user defined #2"},
- {0},
- };
-
- ObjcType encodings[] = {
- { _C_ID, "0x%06lx", "id"},
- { _C_CLASS, "0x%06lx", "Class"},
- { _C_SEL, "%s", "SEL"},
- { _C_CHR, "%c", "char"},
- { _C_UCHR, "%c", "unsigned char"},
- { _C_SHT, "%s", "short"},
- { _C_USHT, "%s", "unsigned short"},
- { _C_INT, "%d", "int"},
- { _C_UINT, "%d", "unsigned int"},
- { _C_LNG, "%l", "long"},
- { _C_ULNG, "%l", "unsigned long"},
- { _C_FLT, "%f", "float"},
- { _C_DBL, "%f", "double"},
- { _C_VOID, "0x%06lx", "void"},
- { _C_PTR, "0x%06lx", "pointer"},
- { _C_CHARPTR, "*s", "char *"},
- { _C_STRUCT_B,"%x", "struct"},
- { 0, "0x%06lx", "Unknown"},
- };
-
- @end
-
-