home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / ExceptionHandler-C-src / MyExceptionHandler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-10  |  5.2 KB  |  169 lines  |  [TEXT/KAHL]

  1. /************************************************************************
  2.     File:    MyExceptionHandler.c
  3.     
  4.     By:        R. Mark Fleming                    Think C V3.02 Signal Routines....
  5.     
  6.     EMail:    flemingm@QUCDN.QueensU.CA
  7.     Phone:    (613) 545-9732 (h), (613) 545-2039 (w)
  8.     SMail:    521 Albert Street
  9.             Kingston, Ont.
  10.             Canada, K7K 4M5
  11.  
  12.     Description:    This is modelled after Apple's MPW's exception handler/
  13.                     Signals routines that are in it's sample code...
  14.                     
  15.     Note: I have uses the same Prototyping as Apple routines (in fact they
  16.             are a copy of apple's prototype def's).
  17.     
  18.     Creation Date:    January 31, 1990
  19.     
  20.     special note:
  21.     I have not tested these routines very well, but they did work to 
  22.     compile Apple's "AppleTalk GetZoneList Sample Application", so use at
  23.     your own risk...
  24.     
  25.     You may use, modify and redistribute BUT NOT SELL this code provided
  26.     that all changes/bug fixes are returned to the author for inclusion.
  27.  
  28. ************************************************************************/
  29.  
  30. #include <asm.h>
  31.  
  32. typedef struct {
  33.     long            regs[11];            /* D3-D7/A2-A7 */
  34.     short            error;
  35.     long            message;
  36.     long            failA6;
  37.     long            failPC;
  38.     Ptr                nextInfo;        /* Handler */
  39.     long            whoPC;            /* Next FI structure */
  40.     short            whatSignals;
  41.     /* this is used to keep the old stack frame return address */
  42.     long            sigFRet;
  43. } FailInfo, *PFailInfo;
  44.  
  45. /* Call the following initialization routine before your other initializations (InitGraf, etc.)-
  46.  in other words as early as you can in the application. */
  47.  
  48. extern pascal void InitUFailure();
  49. /* Allocates the heap block for CatchSignals and initializes the global
  50.     variables used by the unit. C programs must use this instead of InitSignals. */
  51.         
  52. extern pascal void Signal(short);
  53. /* Returns control to the point of the last CatchSignal/CatchFailures.  The program will
  54.     then behave as though that CatchSignal had returned with the code parameter
  55.     supplied to Signal. If CatchCFailures is catching, the message parameter will be 0. */
  56.         
  57. extern pascal void SignalMessage(short, long);
  58. /* Returns control to the point of the last CatchSignal.
  59.     If CatchCFailures is catching, the message parameter will be returned. */
  60.  
  61. extern pascal void CatchCFailures(/* FailInfo *, ProcPtr */);
  62. /* Call this to set up an exception handler. This pushes your handler onto
  63.         a stack of exception handlers. */
  64.  
  65. extern pascal void Failure(/* short, long */);
  66. /* Call this to signal a failure.  Control will branch to the most recent
  67.         exception handler, which will be popped off the handler stack. */
  68.  
  69. extern pascal void Success(FailInfo *);
  70. /* Call this when you want to de-install your exception handler (pop 1
  71.         element off the handler stack). */
  72.         
  73. /*********************************************************/        
  74.         
  75. static FailInfo *Sig;    
  76.  
  77. /*********************************************************/        
  78.     
  79. pascal void InitUFailure()
  80. /* Allocates the heap block for CatchSignals and initializes the global
  81.     variables used by the unit. No CatchSignals from the main level
  82.     of Pascal are allowed if you use InitUFailure.
  83.     [C programs must use this instead of InitSignals.] */
  84. {
  85.     Sig = 0L;
  86. }
  87.  
  88. /* Note: CatchCFailures() has 2 parameters, but to stop Think C from creating
  89.         LINK A6 code, they are left out....
  90. */
  91. pascal void CatchCFailures()
  92. /* Call this to set up an exception handler. This pushes your handler onto
  93.         a stack of exception handlers. */
  94. {    asm {        
  95.         MOVE.L    (A7)+,D2                ; Return Address        
  96.         MOVE.L    (A7)+,d0                ; Handler address    
  97.         MOVE.L    (A7)+,A0                ;fi        
  98.         MOVEM.L A2-A7/D3-D7,(A0)        ; save Reg. & Restored Stack pointer.
  99.         CLR.W    OFFSET(FailInfo,error)(a0)    
  100.         CLR.L    OFFSET(FailInfo,message)(a0)    
  101.         MOVE.L    Sig,D1                    ;Add this Record to Link List.
  102.         MOVE.L    a0,Sig
  103.         MOVE.L    D1,OFFSET(FailInfo,whoPC)(a0)    
  104.         MOVE.L    D0,OFFSET(FailInfo,nextInfo)(a0)    ;Clean Up routine to call..    
  105.         MOVE.L    D2,OFFSET(FailInfo,sigFRet)(a0)        ;Save Return Address..
  106.  
  107.         MOVE.L    D2,A0                        ;get return address
  108.         JMP        (A0)    
  109.         }
  110. }
  111.  
  112. pascal void Failure()
  113. /*
  114. int error;
  115. long message;
  116.     Call this to signal a failure.  Control will branch to the most recent
  117.     exception handler, which will be popped off the handler stack. */
  118. {    /* DebugStr("\pFailure"); */
  119.     asm {
  120.         MOVE.L    Sig,A0
  121.         move.l    a0,d0
  122.         bne.s    @1        
  123.         move.l    (a7)+,a0    ;Get Return Address
  124.         move.l    (a7)+,d0    ;Pop message off stack
  125.         move.w    (a7)+,d0    ;Pop error off Stack
  126.         jmp (a0)            ; Return to caller.
  127. @1        
  128.         move.l    (a7)+,OFFSET(FailInfo,failPC)(a0)    ;Pop Old Return Address
  129.         MOVEM.L (A0),A2-A7/D3-D7                    ;Restore Old Registers..
  130.         
  131.         MOVE.L    OFFSET(FailInfo,nextInfo)(a0),a1    ;Get Clean Routine
  132.         move.l    a1,d0
  133.         BEQ.s    @2
  134.         jsr    (a1)            ;Call if not NULL
  135. @2        
  136.         MOVE.L    Sig,A0                
  137.         MOVE.w    OFFSET(FailInfo,error)(a0),d0    ;Set Return Code!!! to Error
  138.         MOVE.L    OFFSET(FailInfo,whoPC)(a0),d1    ;Pop off Stack.
  139.         MOVE.L    d1,Sig                            ;ie. Remove from Link List.
  140.         MOVE.L    OFFSET(FailInfo,sigFRet)(a0),a0    ;Goto catch place...
  141.         jmp (a0) 
  142.  
  143.         }
  144. }
  145.  
  146. pascal void Success(fi)
  147. FailInfo *fi;
  148. /* Call this when you want to de-install your exception handler
  149.     (pop 1 element off the handler stack). */
  150. {
  151.     if (Sig) Sig = (FailInfo *) Sig->whoPC;        /* Pop Off Stack */
  152. }
  153.  
  154. pascal void SignalMessage(code, message)
  155. int code;
  156. long message;
  157. {
  158.     Failure(code, message);
  159.     Debugger();    /* Should never Reach this... */
  160. }
  161.  
  162. pascal void Signal(code)
  163. int code;
  164. {
  165.         if (code) {
  166.             Failure(code, 0);
  167.             Debugger();
  168.             }
  169. }