home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / News / Alexandra.0.82 / Source / AMGErrorHandling.subproj / EMErrorInfo.m < prev    next >
Encoding:
Text File  |  1996-01-30  |  9.3 KB  |  395 lines

  1.  
  2. #import "EMErrorDescription.h"
  3. #import "EMErrorInfo.h"
  4. #import "EMErrorManager.h"
  5. #import <appkit/appkit.h>
  6.  
  7. #define MAX_FUNCTION_ARGS  3        // Print at most three args to a function
  8. #define MAX_FRAMES 50
  9.  
  10.  
  11. typedef struct _type  
  12.     {
  13.     char    encoding;
  14.     char    *format;
  15.     char    *name;
  16.     } ParType;
  17.  
  18.  
  19. @implementation EMErrorInfo:Object
  20.  
  21. //--------------------------------------------------------------------------------
  22. // GLOBALE VARIABLEN (mehr der Uebersicht halber hier)
  23. //--------------------------------------------------------------------------------
  24.  
  25. static ParType encodings[] = {    
  26.             {_C_ID,            "0x%06lx",        "id"},
  27.             {_C_CLASS,        "0x%06lx",        "Class"},
  28.             {_C_SEL,        "@selector(%s)","SEL"},
  29.             {_C_CHR,        "%c",            "char"},
  30.             {_C_UCHR,        "%c",            "unsigned char"},
  31.             {_C_SHT,        "%s",            "short"},
  32.             {_C_USHT,        "%c",            "unsigned short"},
  33.             {_C_INT,        "%d",            "int"},
  34.             {_C_UINT,        "%d",            "unsigned int"},
  35.             {_C_LNG,        "%l",            "long"},
  36.             {_C_ULNG,        "%l",            "unsigned long"},
  37.             {_C_FLT,        "%f",            "float"},
  38.             {_C_DBL,        "%f",            "double"},
  39.             {_C_VOID,        "0x%06lx",        "void"},
  40.             {_C_PTR,        "0x%06lx",        "ptr"},
  41.             {_C_CHARPTR,    "\"%s\"",        "char *"},
  42.             {_C_STRUCT_B,    "%x",            "struct"},
  43.             {0,                "0x%06lx",        "unknown type"}};
  44.  
  45.  
  46. //--------------------------------------------------------------------------------
  47. // INITIALIZER
  48. //--------------------------------------------------------------------------------
  49.  
  50. + newWithCode:(int)ncode userInfo:(const void *)a:(const void *)b;
  51.     {
  52.     return [[EMErrorInfo alloc] initWithCode:ncode userInfo:a:b];
  53.     }
  54.  
  55.  
  56. + newWithCode:(int)ncode userInfo:(const void *)a:(const void *)b
  57.     file:(const char *)loc line:(int)line;
  58.     {
  59.     return [[EMErrorInfo alloc] initWithCode:ncode userInfo:a:b 
  60.                     file:loc line:line];
  61.     }
  62.  
  63.  
  64. //--------------------------------------------------------------------------------
  65. // INIT & FREE
  66. //--------------------------------------------------------------------------------
  67.  
  68. - initWithCode:(int)ncode userInfo:(const void *)a:(const void *)b;    
  69.     {
  70.     return [self initWithCode:ncode userInfo:a:b file:"?" line:0];
  71.     }
  72.     
  73.  
  74. - initWithCode:(int)ncode userInfo:(const void *)a:(const void *)b
  75.     file:(const char *)loc line:(int)line;
  76.     {
  77.     char    buf[MAXPATHLEN+1]="?";
  78.     
  79.     [super init];
  80.     if(line>0)
  81.         sprintf(buf,"%s %d",loc,line);
  82.     code=ncode;
  83.     location=NXCopyStringBufferFromZone(buf,[self zone]);
  84.     stackFrame=NULL;
  85.     userData1=a;
  86.     userData2=b;
  87.     time(&timet);
  88.     message=timeStamp=NULL;
  89.     return self;
  90.     }
  91.  
  92.  
  93. - free
  94.     {
  95.     NXZoneFree([self zone],location);
  96.     if(timeStamp)
  97.         NXZoneFree([self zone],timeStamp);
  98.     if(message)
  99.         NXZoneFree([self zone],message);
  100.     if(stackFrame)
  101.         NXZoneFree([self zone],stackFrame);
  102.     if(userData1)
  103.         {
  104.         if(userData1Free=='s')
  105.             NX_FREE((void *)userData1);
  106.         else if(userData1Free=='o')
  107.             [(id)userData1 free];
  108.         }
  109.     if(userData2)
  110.         {
  111.         if(userData2Free=='s')
  112.             NX_FREE((void *)userData2);
  113.         else if(userData2Free=='o')
  114.             [(id)userData2 free];
  115.         }
  116.     return [super free];
  117.     }
  118.  
  119.  
  120. //--------------------------------------------------------------------------------
  121. // I-VAR
  122. //--------------------------------------------------------------------------------
  123.  
  124. - setUDFreeSemantics:(const char *)desc;
  125.     {
  126.     userData1Free=desc[0];
  127.     userData2Free=desc[1];
  128.     return self;
  129.     }
  130.     
  131.  
  132. //--------------------------------------------------------------------------------
  133. // I-VAR
  134. //--------------------------------------------------------------------------------
  135.  
  136. - (int)code;
  137.     {
  138.     return code;
  139.     }
  140.     
  141.  
  142. - (time_t)time;
  143.     {
  144.     return timet;
  145.     }
  146.     
  147.  
  148. - (const char *)location;
  149.     {
  150.     return location;
  151.     }
  152.     
  153.  
  154. - (const char *)stack;
  155.     {
  156.     return stackFrame;
  157.     }
  158.  
  159.  
  160. - (const void *)userData1;
  161.     {
  162.     return userData1;
  163.     }
  164.     
  165.     
  166. - (const void *)userData2;
  167.     {
  168.     return userData2;
  169.     }
  170.     
  171.  
  172. //--------------------------------------------------------------------------------
  173. // Convenience
  174. //--------------------------------------------------------------------------------
  175.  
  176. - (const char *)message;
  177.     {
  178.     if(!message)
  179.         {
  180.         char buf[1000];
  181.         
  182.         sprintf(buf,[[ERROR_MANAGER errorDescriptionFor:code] msg],
  183.                         userData1,userData2);
  184.         message=NXCopyStringBufferFromZone(buf,[self zone]);
  185.         }
  186.     return message;
  187.     }
  188.  
  189.  
  190. - (const char *)timeStamp;
  191.     {
  192.     if(!timeStamp)
  193.         {
  194.         char buf[90];
  195.         
  196.         strftime(buf,89,"%d %b %y %H:%M:%S %Z",localtime(&timet));
  197.         timeStamp=NXCopyStringBufferFromZone(buf,[self zone]);
  198.         }
  199.     return timeStamp;
  200.     }
  201.     
  202.  
  203. - (NXAtom)exceptionClass;
  204.     {
  205.     return [[ERROR_MANAGER errorDescriptionFor:code] exceptionClass];
  206.     }
  207.  
  208.  
  209. - (const char *)codeString;
  210.     {
  211.     static char string[20];
  212.     
  213.     switch([self source])
  214.         {
  215.     case EMSourceApplication: sprintf(string,"A%d",code-EM_APPBASE); break;
  216.     case EMSourceSignal:       sprintf(string,"S%d",code-EM_SIGBASE); break;
  217.     case EMSourceInternal:      sprintf(string,"I%d",code-EM_INTBASE); break;
  218.     case EMSourceKit:          sprintf(string,"K%d",code);             break;
  219.         }
  220.     return string;
  221.     }
  222.  
  223.  
  224. - (EMErrorSource)source;
  225.     {
  226.     if(code>=EM_APPBASE)
  227.         return EMSourceApplication;
  228.     else if(code>=EM_SIGBASE)
  229.         return EMSourceSignal;
  230.     else if(code>=EM_INTBASE)
  231.         return EMSourceInternal;
  232.     return EMSourceKit;
  233.     }
  234.  
  235.     
  236. //--------------------------------------------------------------------------------
  237. // Hilfsmethoden, um den Kontext zu speichern zu koennen.
  238. //--------------------------------------------------------------------------------
  239. //        ASSUMPTION:  The layout of a stack frame for a method invocation is:
  240. //            fp+0 bytes:        calling frame
  241. //            fp+4 bytes:        calling pc
  242. //            fp+8 bytes:        self
  243. //            fp+12 bytes:    selector for method invoked
  244. //            fp+16 bytes:    first (overt) argument
  245. //
  246. //        ASSUMPTION: The layout of a stack frame for a function invocation is:
  247. //            fp+0 bytes:        calling frame
  248. //            fp+4 bytes:        calling pc
  249. //            fp+8 bytes:        first argument
  250. //
  251. //        Clearly these are shady assumptions, however we're already
  252. //        in the process of crashing, so what harm can be done?
  253. //--------------------------------------------------------------------------------
  254.  
  255.  
  256. - printFunctionFromFP:(void *)framePointer into:(char *)buffer
  257.     {
  258.     char    argStrg[20];
  259.     void    *argStart;
  260.     long    argNum;    // Index into arguments;
  261.     
  262.     strcat(buffer,"function(");
  263.     argStart=framePointer+8;
  264.     for(argNum=0;argNum<MAX_FUNCTION_ARGS;argNum++)  
  265.         {
  266.         sprintf(argStrg,"%s0x%06lx",
  267.                 ((argNum>0)?", ":""),*(((unsigned long *)argStart)+argNum));
  268.         strcat(buffer,argStrg);
  269.         }
  270.     strcat(buffer,")\n");
  271.     return self;
  272.     }
  273.  
  274.  
  275. - printMethodFromFP:(void *)framePointer into:(char *)buffer
  276.     {
  277.     char     tmp[256],selStrg[200],*selPart;
  278.     SEL     selector;
  279.     id         object;
  280.     Method     m;
  281.     BOOL     isClassMethod;
  282.  
  283.     object=*(id *)(framePointer+8);       // receiver is 8 bytes from fp
  284.     selector=*(SEL *)(framePointer+12);  // selector is 12 bytes from fp
  285.     isClassMethod=([object class]==object);
  286.     
  287.     sprintf(tmp,"%c[%s",(isClassMethod?'+':'-'),object_getClassName(object));
  288.     strcat(buffer,tmp);
  289.     strcpy(selStrg,sel_getName(selector));
  290.     
  291.     if(isClassMethod)
  292.         m=class_getClassMethod([object class],selector);
  293.     else
  294.         m=class_getInstanceMethod([object class],selector);
  295.     
  296.     if(m)
  297.         {
  298.         void     *argStart=(framePointer+8);
  299.         int     argNum,argCount,offset;
  300.         char    *type;
  301.         
  302.         argCount=method_getNumberOfArguments(m);
  303.         if(argCount==2)
  304.             {
  305.             strcat(buffer," ");
  306.             strcat(buffer,selStrg);
  307.             }
  308.         else
  309.             for(argNum=2,selPart=strtok(selStrg,":");
  310.                 argNum<argCount;
  311.                 argNum++,selPart=strtok(NULL,":"))        
  312.                 {
  313.                 ParType *cur;
  314.                 long    arg;
  315.                 
  316.                 method_getArgumentInfo(m,argNum,&type,&offset);
  317.                 arg=*(long *)(argStart+offset);
  318.                 for (cur=encodings;cur->encoding;cur++)
  319.                     if (cur->encoding == type[0])
  320.                         break;
  321.                 if(selPart)
  322.                     sprintf(tmp," %s:(%s)",selPart?selPart:"",cur->name);
  323.                 else
  324.                     sprintf(tmp,":(%s)",cur->name);
  325.                 strcat(buffer,tmp);
  326.                 if(arg==0 && type[0]==_C_SEL)
  327.                     sprintf(tmp,"{unknown method}");
  328.                 else
  329.                     sprintf(tmp,cur->format,arg);
  330.                 strcat(buffer,tmp);
  331.                 }
  332.         strcat(buffer,"]\n");
  333.         }  
  334.     else
  335.         {
  336.         sprintf(tmp," %s] {unknown method}\n",selStrg);
  337.         strcat(buffer,tmp);
  338.         }
  339.     return self;
  340.     }
  341.  
  342.  
  343. - dumpBacktraceInto:(char *)buf;
  344.     {
  345.     void             *framePointer;    // pointer to current frame
  346.     unsigned int     frameCount;        // counter for number of frames printed
  347.         
  348.     
  349.     framePointer=((void *)&self)-8;    // Start the frame pointer off at our frame
  350.     framePointer=(void *)*(long *)framePointer;  // go up one frame
  351.     frameCount=0;
  352.     
  353.     // Assume that a whole lotta frames means either (a) we're trashed or
  354.     // (b) we're in a recursive deathtrap.  In the latter case, we've
  355.     // probably got enough info to see a whole cycle.
  356.     
  357.     while(frameCount<MAX_FRAMES && framePointer)
  358.         { // If this frame is a method call we'll have a valid selector at (fp+12).
  359.         if (sel_isMapped(*(SEL *)(framePointer+12))) 
  360.             [self printMethodFromFP:framePointer into:buf];
  361.         else
  362.             [self printFunctionFromFP:framePointer into:buf];
  363.         frameCount++;
  364.         framePointer=(void *)*(long *)framePointer;  // go up one frame
  365.         }
  366.     return self;
  367.     }
  368.  
  369.  
  370. - getContext;
  371.     {
  372.     char     *buf;
  373.     
  374.     time(&timet);
  375. #if m68k || i386
  376.     buf=NXZoneCalloc([self zone],20*1024,sizeof(char));
  377.     [self dumpBacktraceInto:buf];
  378.     stackFrame=NXZoneRealloc([self zone],buf,strlen(buf+1));
  379. #elif hppa || sparc
  380.     stackFrame=NXCopyStringBufferFromZone("<<Can't dump stack on "
  381.             "architecture " __ARCHITECTURE__ " yet>>\n",[self zone]);
  382. #else
  383.     stackFrame=NXCopyStringBufferFromZone("<<Can't dump stack on "
  384.             "unknown architecture " __ARCHITECTURE__ ">>\n",[self zone]);
  385. #endif
  386.     return self;    
  387.     }
  388.  
  389.  
  390. //--------------------------------------------------------------------------------
  391. // THAT'S IT
  392. //--------------------------------------------------------------------------------
  393.  
  394. @end
  395.