home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -seriously_amiga- / programming / other / blowup / source / showcrashinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-27  |  6.0 KB  |  232 lines

  1. /*
  2.  * $Id: showcrashinfo.c 1.6 1998/04/18 15:45:22 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * Blowup -- Catches and displays task errors
  7.  *
  8.  * Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  9.  * Public Domain
  10.  */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "global.h"
  14. #endif    /* _GLOBAL_H */
  15.  
  16. /******************************************************************************/
  17.  
  18. #define TROUBLE    (-1)    /* could not open the requester */
  19. #define REBOOT    ( 0)    /* user wants to reboot the machine */
  20. #define SUSPEND    ( 1)    /* user wants the trapped task to be suspended */
  21.  
  22. /******************************************************************************/
  23.  
  24. STATIC LONG
  25. ShowEasyRequest(
  26.     const STRPTR    title,
  27.     const STRPTR    gadgets,
  28.     const STRPTR    text,
  29.                     ...)
  30. {
  31.     struct Process * thisProcess;
  32.     struct Window * parentWindow;
  33.     LONG result = TROUBLE;
  34.  
  35.     /* set up the parent window pointer so the requester will
  36.      * open on the program's preferred screen; this works only
  37.      * for processes, which may not want this requester to show
  38.      * up in the first place
  39.      */
  40.  
  41.     parentWindow = NULL;
  42.  
  43.     thisProcess = (struct Process *)FindTask(NULL);
  44.     if(thisProcess->pr_Task.tc_Node.ln_Type == NT_PROCESS)
  45.     {
  46.         parentWindow = thisProcess->pr_WindowPtr;
  47.     }
  48.  
  49.     /* if the pointer is invalid, do not show the requester */
  50.     if(parentWindow != (struct Window *)~0)
  51.     {
  52.         struct EasyStruct es;
  53.         va_list varArgs;
  54.     
  55.         es.es_StructSize    = sizeof(es);
  56.         es.es_Flags            = NULL;
  57.         es.es_Title            = (STRPTR)title;
  58.         es.es_TextFormat    = (STRPTR)text;
  59.         es.es_GadgetFormat    = (STRPTR)gadgets;
  60.     
  61.         va_start(varArgs,text);
  62.         result = EasyRequestArgs(parentWindow,&es,NULL,(APTR)varArgs);
  63.         va_end(varArgs);
  64.     }
  65.  
  66.     return(result);
  67. }
  68.  
  69. /******************************************************************************/
  70.  
  71. VOID ASM
  72. ShowCrashInfo(
  73.     REG(d0) UBYTE    trapType,
  74.     REG(d1) ULONG    pc,
  75.     REG(d2) UWORD    sr,
  76.     REG(a0) ULONG *    stackFrame)
  77. {
  78.     /* a short table to associate trap types with human-readable information */
  79.     STATIC const struct { ULONG Type; STRPTR Name; } TrapTypes[] =
  80.     {
  81.         2,    "Bus error",
  82.         3,    "Address error",
  83.         4,    "Illegal instruction",
  84.         5,    "Zero divide",
  85.         6,    "CHK, CHK2 instructions",
  86.         7,    "cpTRAPc, TRAPcc, TRAPV instructions",
  87.         8,    "Privilege violation",
  88.         9,    "Trace",
  89.         10,    "Line 1010 emulator",
  90.         11,    "Line 1111 emulator",
  91.         13,    "Coprocessor protocol violation",
  92.         14,    "Stack frame format error",
  93.         15,    "Uninitialized interrupt",
  94.         24,    "Spurious interrupt",
  95.         25,    "Level 1 interrupt autovector (SOFTINT, DSKBLK, TBE)",
  96.         26,    "Level 2 interrupt autovector (PORTS)",
  97.         27,    "Level 3 interrupt autovector (COPER, VERTB, BLIT)",
  98.         28,    "Level 4 interrupt autovector (AUD2, AUD0, AUD3, AUD1)",
  99.         29,    "Level 5 interrupt autovector (RBF, DSKSYNC)",
  100.         30,    "Level 6 interrupt autovector (EXTER)",
  101.         31,    "Level 7 interrupt autovector (NMI)",
  102.         32,    "TRAP #0 instruction",
  103.         33,    "TRAP #1 instruction",
  104.         34,    "TRAP #2 instruction",
  105.         35,    "TRAP #3 instruction",
  106.         36,    "TRAP #4 instruction",
  107.         37,    "TRAP #5 instruction",
  108.         38,    "TRAP #6 instruction",
  109.         39,    "TRAP #7 instruction",
  110.         40,    "TRAP #8 instruction",
  111.         41,    "TRAP #9 instruction",
  112.         42,    "TRAP #10 instruction",
  113.         43,    "TRAP #11 instruction",
  114.         44,    "TRAP #12 instruction",
  115.         45,    "TRAP #13 instruction",
  116.         46,    "TRAP #14 instruction",
  117.         47,    "TRAP #15 instruction",
  118.         48,    "FPCP Branch or Set on unordered condition",
  119.         49,    "FPCP inexact result",
  120.         50,    "FPCP divide by zero",
  121.         51,    "FPCP underflow",
  122.         52,    "FPCP operand error",
  123.         53,    "FPCP overflow",
  124.         54,    "FPCP signaling NAN",
  125.         56,    "MMU configuration error",
  126.         57,    "MMU illegal operation error",
  127.         58,    "MMU access level violation error"
  128.     };
  129.  
  130.     UBYTE errorBuffer[40];
  131.     STRPTR errorType;
  132.     int i;
  133.  
  134.     /* we really are busy now */
  135.     ObtainSemaphoreShared(&BusySemaphore);
  136.  
  137.     /* find an explanation for the exception condition */
  138.     errorType = NULL;
  139.     for(i = 0 ; i < NUM_ELEMENTS(TrapTypes) ; i++)
  140.     {
  141.         if(TrapTypes[i].Type == trapType)
  142.         {
  143.             errorType = (STRPTR)TrapTypes[i].Name;
  144.             break;
  145.         }
  146.     }
  147.  
  148.     /* if no explanation could be found, just list the trap number */
  149.     if(errorType == NULL)
  150.     {
  151.         errorType = errorBuffer;
  152.  
  153.         SPrintfN(sizeof(errorBuffer),errorBuffer,"Exception #%ld",trapType);
  154.     }
  155.  
  156.     /* show the error and the status information */
  157.     VoiceComplaint(trapType,sr,pc,stackFrame,"%s\n",errorType);
  158.  
  159.     /* now check whether the exception came from supervisor mode
  160.      * or whether it was triggered from an interrupt; if that
  161.      * happens, we will know that we are in trouble and thus
  162.      * fall straight into a dead-end alert
  163.      */
  164.     if((sr & 0x2700) != 0)
  165.     {
  166.         Alert(AT_DeadEnd | trapType);
  167.     }
  168.     else
  169.     {
  170.         UBYTE nameBuffer[MAX_FILENAME_LEN];
  171.         struct Process * thisProcess;
  172.         STRPTR taskType;
  173.         LONG response;
  174.  
  175.         /* determine the name and the type of the current task */
  176.         thisProcess = (struct Process *)FindTask(NULL);
  177.     
  178.         StrcpyN(sizeof(nameBuffer),nameBuffer,thisProcess->pr_Task.tc_Node.ln_Name);
  179.     
  180.         if(thisProcess->pr_Task.tc_Node.ln_Type == NT_PROCESS)
  181.         {
  182.             struct CommandLineInterface * cli;
  183.     
  184.             taskType = "Process";
  185.     
  186.             cli = BADDR(thisProcess->pr_CLI);
  187.             if(cli != NULL)
  188.             {
  189.                 if(cli->cli_CommandName != NULL)
  190.                 {
  191.                     SPrintfN(sizeof(nameBuffer),nameBuffer,"%b",cli->cli_CommandName);
  192.                     taskType = "Shell program";
  193.                 }
  194.             }
  195.         }
  196.         else
  197.         {
  198.             taskType = "Task";
  199.         }
  200.     
  201.         /* say what happened and ask the user to decide what to do next */
  202.         response = ShowEasyRequest("Software error","Suspend|Reboot",
  203.             "%s \"%s\" stopped.\n\n"
  204.             "Finish ALL disk activity\n"
  205.             "before you select \"Reboot\"!",taskType,nameBuffer);
  206.     
  207.         /* release the busy semaphore, but without allowing multitasking
  208.          * to resume; that would be a bad idea because we are not going
  209.          * to be busy any more in a minute but wouldn't want anyone else
  210.          * to consider us busy until we have actually gone into suspension
  211.          */
  212.         Forbid();
  213.  
  214.         ReleaseSemaphore(&BusySemaphore);
  215.     
  216.         /* if the requester did not open or if the task was to be
  217.          * suspended, wait forever for a signal that will never arrive
  218.          */
  219.         if(response == TROUBLE || response == SUSPEND)
  220.         {
  221.             Wait(0);
  222.         }
  223.         else
  224.         {
  225.             /* drop straight into a dead-end alert that
  226.              * will eventually trigger a reboot
  227.              */
  228.             Alert(AT_DeadEnd | trapType);
  229.         }
  230.     }
  231. }
  232.