home *** CD-ROM | disk | FTP | other *** search
-
- #import "EMErrorDescription.h"
- #import "EMErrorInfo.h"
- #import "EMErrorManager.h"
- #import <appkit/appkit.h>
-
- #define MAX_FUNCTION_ARGS 3 // Print at most three args to a function
- #define MAX_FRAMES 50
-
-
- typedef struct _type
- {
- char encoding;
- char *format;
- char *name;
- } ParType;
-
-
- @implementation EMErrorInfo:Object
-
- //--------------------------------------------------------------------------------
- // GLOBALE VARIABLEN (mehr der Uebersicht halber hier)
- //--------------------------------------------------------------------------------
-
- static ParType encodings[] = {
- {_C_ID, "0x%06lx", "id"},
- {_C_CLASS, "0x%06lx", "Class"},
- {_C_SEL, "@selector(%s)","SEL"},
- {_C_CHR, "%c", "char"},
- {_C_UCHR, "%c", "unsigned char"},
- {_C_SHT, "%s", "short"},
- {_C_USHT, "%c", "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", "ptr"},
- {_C_CHARPTR, "\"%s\"", "char *"},
- {_C_STRUCT_B, "%x", "struct"},
- {0, "0x%06lx", "unknown type"}};
-
-
- //--------------------------------------------------------------------------------
- // INITIALIZER
- //--------------------------------------------------------------------------------
-
- + newWithCode:(int)ncode userInfo:(const void *)a:(const void *)b;
- {
- return [[EMErrorInfo alloc] initWithCode:ncode userInfo:a:b];
- }
-
-
- + newWithCode:(int)ncode userInfo:(const void *)a:(const void *)b
- file:(const char *)loc line:(int)line;
- {
- return [[EMErrorInfo alloc] initWithCode:ncode userInfo:a:b
- file:loc line:line];
- }
-
-
- //--------------------------------------------------------------------------------
- // INIT & FREE
- //--------------------------------------------------------------------------------
-
- - initWithCode:(int)ncode userInfo:(const void *)a:(const void *)b;
- {
- return [self initWithCode:ncode userInfo:a:b file:"?" line:0];
- }
-
-
- - initWithCode:(int)ncode userInfo:(const void *)a:(const void *)b
- file:(const char *)loc line:(int)line;
- {
- char buf[MAXPATHLEN+1]="?";
-
- [super init];
- if(line>0)
- sprintf(buf,"%s %d",loc,line);
- code=ncode;
- location=NXCopyStringBufferFromZone(buf,[self zone]);
- stackFrame=NULL;
- userData1=a;
- userData2=b;
- time(&timet);
- message=timeStamp=NULL;
- return self;
- }
-
-
- - free
- {
- NXZoneFree([self zone],location);
- if(timeStamp)
- NXZoneFree([self zone],timeStamp);
- if(message)
- NXZoneFree([self zone],message);
- if(stackFrame)
- NXZoneFree([self zone],stackFrame);
- if(userData1)
- {
- if(userData1Free=='s')
- NX_FREE((void *)userData1);
- else if(userData1Free=='o')
- [(id)userData1 free];
- }
- if(userData2)
- {
- if(userData2Free=='s')
- NX_FREE((void *)userData2);
- else if(userData2Free=='o')
- [(id)userData2 free];
- }
- return [super free];
- }
-
-
- //--------------------------------------------------------------------------------
- // I-VAR
- //--------------------------------------------------------------------------------
-
- - setUDFreeSemantics:(const char *)desc;
- {
- userData1Free=desc[0];
- userData2Free=desc[1];
- return self;
- }
-
-
- //--------------------------------------------------------------------------------
- // I-VAR
- //--------------------------------------------------------------------------------
-
- - (int)code;
- {
- return code;
- }
-
-
- - (time_t)time;
- {
- return timet;
- }
-
-
- - (const char *)location;
- {
- return location;
- }
-
-
- - (const char *)stack;
- {
- return stackFrame;
- }
-
-
- - (const void *)userData1;
- {
- return userData1;
- }
-
-
- - (const void *)userData2;
- {
- return userData2;
- }
-
-
- //--------------------------------------------------------------------------------
- // Convenience
- //--------------------------------------------------------------------------------
-
- - (const char *)message;
- {
- if(!message)
- {
- char buf[1000];
-
- sprintf(buf,[[ERROR_MANAGER errorDescriptionFor:code] msg],
- userData1,userData2);
- message=NXCopyStringBufferFromZone(buf,[self zone]);
- }
- return message;
- }
-
-
- - (const char *)timeStamp;
- {
- if(!timeStamp)
- {
- char buf[90];
-
- strftime(buf,89,"%d %b %y %H:%M:%S %Z",localtime(&timet));
- timeStamp=NXCopyStringBufferFromZone(buf,[self zone]);
- }
- return timeStamp;
- }
-
-
- - (NXAtom)exceptionClass;
- {
- return [[ERROR_MANAGER errorDescriptionFor:code] exceptionClass];
- }
-
-
- - (const char *)codeString;
- {
- static char string[20];
-
- switch([self source])
- {
- case EMSourceApplication: sprintf(string,"A%d",code-EM_APPBASE); break;
- case EMSourceSignal: sprintf(string,"S%d",code-EM_SIGBASE); break;
- case EMSourceInternal: sprintf(string,"I%d",code-EM_INTBASE); break;
- case EMSourceKit: sprintf(string,"K%d",code); break;
- }
- return string;
- }
-
-
- - (EMErrorSource)source;
- {
- if(code>=EM_APPBASE)
- return EMSourceApplication;
- else if(code>=EM_SIGBASE)
- return EMSourceSignal;
- else if(code>=EM_INTBASE)
- return EMSourceInternal;
- return EMSourceKit;
- }
-
-
- //--------------------------------------------------------------------------------
- // Hilfsmethoden, um den Kontext zu speichern zu koennen.
- //--------------------------------------------------------------------------------
- // ASSUMPTION: The layout of a stack frame for a method invocation is:
- // fp+0 bytes: calling frame
- // fp+4 bytes: calling pc
- // fp+8 bytes: self
- // fp+12 bytes: selector for method invoked
- // fp+16 bytes: first (overt) argument
- //
- // ASSUMPTION: The layout of a stack frame for a function invocation is:
- // fp+0 bytes: calling frame
- // fp+4 bytes: calling pc
- // fp+8 bytes: first argument
- //
- // Clearly these are shady assumptions, however we're already
- // in the process of crashing, so what harm can be done?
- //--------------------------------------------------------------------------------
-
-
- - printFunctionFromFP:(void *)framePointer into:(char *)buffer
- {
- char argStrg[20];
- void *argStart;
- long argNum; // Index into arguments;
-
- strcat(buffer,"function(");
- argStart=framePointer+8;
- for(argNum=0;argNum<MAX_FUNCTION_ARGS;argNum++)
- {
- sprintf(argStrg,"%s0x%06lx",
- ((argNum>0)?", ":""),*(((unsigned long *)argStart)+argNum));
- strcat(buffer,argStrg);
- }
- strcat(buffer,")\n");
- return self;
- }
-
-
- - printMethodFromFP:(void *)framePointer into:(char *)buffer
- {
- char tmp[256],selStrg[200],*selPart;
- SEL selector;
- id object;
- Method m;
- BOOL isClassMethod;
-
- object=*(id *)(framePointer+8); // receiver is 8 bytes from fp
- selector=*(SEL *)(framePointer+12); // selector is 12 bytes from fp
- isClassMethod=([object class]==object);
-
- sprintf(tmp,"%c[%s",(isClassMethod?'+':'-'),object_getClassName(object));
- strcat(buffer,tmp);
- strcpy(selStrg,sel_getName(selector));
-
- if(isClassMethod)
- m=class_getClassMethod([object class],selector);
- else
- m=class_getInstanceMethod([object class],selector);
-
- if(m)
- {
- void *argStart=(framePointer+8);
- int argNum,argCount,offset;
- char *type;
-
- argCount=method_getNumberOfArguments(m);
- if(argCount==2)
- {
- strcat(buffer," ");
- strcat(buffer,selStrg);
- }
- else
- for(argNum=2,selPart=strtok(selStrg,":");
- argNum<argCount;
- argNum++,selPart=strtok(NULL,":"))
- {
- ParType *cur;
- long arg;
-
- method_getArgumentInfo(m,argNum,&type,&offset);
- arg=*(long *)(argStart+offset);
- for (cur=encodings;cur->encoding;cur++)
- if (cur->encoding == type[0])
- break;
- if(selPart)
- sprintf(tmp," %s:(%s)",selPart?selPart:"",cur->name);
- else
- sprintf(tmp,":(%s)",cur->name);
- strcat(buffer,tmp);
- if(arg==0 && type[0]==_C_SEL)
- sprintf(tmp,"{unknown method}");
- else
- sprintf(tmp,cur->format,arg);
- strcat(buffer,tmp);
- }
- strcat(buffer,"]\n");
- }
- else
- {
- sprintf(tmp," %s] {unknown method}\n",selStrg);
- strcat(buffer,tmp);
- }
- return self;
- }
-
-
- - dumpBacktraceInto:(char *)buf;
- {
- void *framePointer; // pointer to current frame
- unsigned int frameCount; // counter for number of frames printed
-
-
- framePointer=((void *)&self)-8; // Start the frame pointer off at our frame
- framePointer=(void *)*(long *)framePointer; // go up one frame
- frameCount=0;
-
- // Assume that a whole lotta frames means either (a) we're trashed or
- // (b) we're in a recursive deathtrap. In the latter case, we've
- // probably got enough info to see a whole cycle.
-
- while(frameCount<MAX_FRAMES && framePointer)
- { // If this frame is a method call we'll have a valid selector at (fp+12).
- if (sel_isMapped(*(SEL *)(framePointer+12)))
- [self printMethodFromFP:framePointer into:buf];
- else
- [self printFunctionFromFP:framePointer into:buf];
- frameCount++;
- framePointer=(void *)*(long *)framePointer; // go up one frame
- }
- return self;
- }
-
-
- - getContext;
- {
- char *buf;
-
- time(&timet);
- #if m68k || i386
- buf=NXZoneCalloc([self zone],20*1024,sizeof(char));
- [self dumpBacktraceInto:buf];
- stackFrame=NXZoneRealloc([self zone],buf,strlen(buf+1));
- #elif hppa || sparc
- stackFrame=NXCopyStringBufferFromZone("<<Can't dump stack on "
- "architecture " __ARCHITECTURE__ " yet>>\n",[self zone]);
- #else
- stackFrame=NXCopyStringBufferFromZone("<<Can't dump stack on "
- "unknown architecture " __ARCHITECTURE__ ">>\n",[self zone]);
- #endif
- return self;
- }
-
-
- //--------------------------------------------------------------------------------
- // THAT'S IT
- //--------------------------------------------------------------------------------
-
- @end
-