#include <exec/alerts.h>
#include <libraries/dos.h>
#include <stdio.h>

#define AO_DiskCopy (AN_DiskCopy >> 24 | 0x00008000)

main(argc,argv)
int argc;
char **argv;
{
   /***** Functions and local variables *****/

   long exp();
   int stch_i();     /* Converts hex string to integer */
   void fputs();

   unsigned long error;    /* User-specified argument */
   char *o;                /* Object of alert, i.e. troublesome subsystem */
   char *s;                /* Specific cause of crash */

   /***** Here we go *****/

   if (argc == 0)             /* Don't let Workbench call us */
      exit (RETURN_ERROR);

   if (argc == 1) {
      fputs ("How can I meditate without a number?\n",stderr);
      exit (RETURN_ERROR);
      }

   if (stch_i(argv[1],&error) == 0) {   /* Put argument into integer */
      fputs ("Usage: ",stdout);
      fputs (argv[0],stdout);
      fputs (" <hex integer>\n",stdout);
      exit (RETURN_WARN);
      }

   /***** Alert object *****/

   switch ((error & 0x7F000000) >> 24 | 0x00008000) {

      case AO_ExecLib      : o = "Exec"; break;
      case AO_GraphicsLib  : o = "Graphics"; break;
      case AO_LayersLib    : o = "Layers library"; break;
      case AO_Intuition    : o = "Intuition"; break;
      case AO_MathLib      : o = "Math library"; break;
      case AO_CListLib     : o = "CList library"; break;
      case AO_DOSLib       : o = "DOS"; break;
      case AO_RAMLib       : o = "RAM library"; break;
      case AO_IconLib      : o = "Icon library"; break;
      case AO_ExpansionLib : o = "Expansion library"; break;
      case AO_AudioDev     : o = "Audio device"; break;
      case AO_ConsoleDev   : o = "Console device"; break;
      case AO_GamePortDev  : o = "Gameport device"; break;
      case AO_KeyboardDev  : o = "Keyboard device"; break;
      case AO_TrackDiskDev : o = "Trackdisk device"; break;
      case AO_TimerDev     : o = "Timer device"; break;
      case AO_CIARsrc      : o = "CIA resource"; break;
      case AO_DiskRsrc     : o = "Disk resource"; break;
      case AO_MiscRsrc     : o = "Misc resource"; break;
      case AO_BootStrap    : o = "Bootstrap"; break;
      case AO_Workbench    : o = "Workbench"; break;
      case AO_DiskCopy     : o = "DiskCopy"; break;
      default              : o = "Unknown subsystem"; break;
      }  /* object */

   /***** Specific error *****/

   switch (error) {

      /* Exec woes */

      case AN_ExcptVect  : s = "bad 68000 exception vector checksum"; break;
      case AN_BaseChkSum : s = "bad ExecBase checksum"; break;
      case AN_LibChkSum  : s = "library checksum failure"; break;
      case AN_LibMem     : s = "insufficient memory to make library"; break;
      case AN_MemCorrupt : s = "corrupted memory list"; break;
      case AN_IntrMem    : s = "insufficient memory for interrupt servers";
                           break;
      case AN_InitAPtr   : s = "InitStruct() of an APTR source"; break;
      case AN_SemCorrupt : s = "illegal semaphore state"; break;
      case AN_FreeTwice  : s = "tried to free memory already freed"; break;
      case AN_BogusExcpt : s = "illegal 680x0 exception taken"; break;

      /* Graphics library */

      case AN_GfxNoMem     : s = "insufficient memory for graphics"; break;
      case AN_LongFrame    : s = "insufficient memory for long frame"; break;
      case AN_ShortFrame   : s = "insufficient memory for short frame"; break;
      case AN_TextTmpRas   : s = "insufficient memory for text TmpRas"; break;
      case AN_BltBitMap    : s = "insufficient memory for BltBitMap"; break;
      case AN_RegionMemory : s = "insufficient memory for regions"; break;
      case AN_MakeVPort    : s = "insufficient memory for MakeVPort"; break;
      case AN_GfxNoLCM     : s = "emergency memory not available"; break;

      /* Layers library */

      case AN_LayersNoMem  : s = "insufficient memory for layers"; break;

      /* Intuition */

      case AN_GadgetType   :
      case AN_BadGadget    : s = "unknown gadget type"; break;
      case AN_CreatePort   : s = "insufficient memory to create port"; break;
      case AN_ItemAlloc    : s = "insufficient memory for item plane"; break;
      case AN_SubAlloc     : s = "insufficient memory for sub alloc"; break;
      case AN_PlaneAlloc   : s = "insufficient memory for plane alloc"; break;
      case AN_ItemBoxTop   : s = "item box top is less than RelZero"; break;
      case AN_OpenScreen   : s = "insufficient memory to open screen"; break;
      case AN_OpenScrnRast : s = "insufficient memory to allocate screen raster";
                             break;
      case AN_SysScrnType  : s = "unknown type of sys screen"; break;
      case AN_AddSWGadget  : s = "insufficient memory to add SW gadgets";
                             break;
      case AN_OpenWindow   : s = "insufficient memory to open window"; break;
      case AN_BadState     : s = "bad state return entering Intuition"; break;
      case AN_BadMessage   : s = "bad message received by IDCMP"; break;
      case AN_WeirdEcho    : s = "weird echo caused incomprehension"; break;
      case AN_NoConsole    : s = "couldn't open the console device"; break;

      /* DOS library */

      case AN_StartMem     : s = "insufficient memory at startup"; break;
      case AN_EndTask      : s = "EndTask didn't"; break;
      case AN_QPktFail     : s = "Qpkt failed"; break;
      case AN_AsyncPkt     : s = "unexpected packet received"; break;
      case AN_FreeVec      : s = "FreeVec failed"; break;
      case AN_DiskBlkSeq   : s = "disk block sequence error"; break;
      case AN_BitMap       : s = "BitMap corrupt"; break;
      case AN_KeyFree      : s = "key already free"; break;
      case AN_BadChkSum    : s = "invalid checksum"; break;
      case AN_DiskError    : s = "disk error"; break;
      case AN_KeyRange     : s = "key out of range"; break;
      case AN_BadOverlay   : s = "bad overlay"; break;

      /* RAM library */

      case AN_BadSegList   : s = "no overlays in library SegLists"; break;

      /* Expansion library */

      case 0x0A000001      : s = "Bad Expansion Free"; break;

      /* Trackdisk device */

      case AN_TDCalibSeek  : s = "seek error on calibration"; break;
      case AN_TDDelay      : s = "error on timer wait"; break;

      /* Timer device */

      case AN_TMBadReq     : s = "bad timer request"; break;
      case AN_TMBadSupply  : s = "power supply doesn't supply ticks"; break;

      /* Disk resource */

      case AN_DRHasDisk    : s = "tried to get unit, but already had disk";
                             break;
      case AN_DRIntNoAct   : s = "no active unit to interrupt"; break;

      /* Bootstrap */

      case AN_BootError    : s = "boot code returned an error"; break;

      /* CPU Traps */

      case 0x00000002      : o = "CPU Trap"; s = "Bus error"; break;
      case 0x00000003      : o = "CPU Trap"; s = "Address error"; break;
      case 0x00000004      : o = "CPU Trap"; s = "Illegal instruction"; break;
      case 0x00000005      : o = "CPU Trap"; s = "Divide-by-Zero"; break;
      case 0x00000006      : o = "CPU Trap"; s = "CHK instruction"; break;
      case 0x00000007      : o = "CPU Trap"; s = "TRAPV instruction"; break;
      case 0x00000008      : o = "CPU Trap"; s = "Privilege violation"; break;
      case 0x00000009      : o = "CPU Trap"; s = "Trace"; break;
      case 0x0000000A      : o = "CPU Trap"; s = "Op Code 1010"; break;
      case 0x0000000B      : o = "CPU Trap"; s = "Op Code 1111"; break;

      /* Don't know specific difficulty, try to determine general problem */

      default : switch (error & 0x00FF0000) {

                   case AG_NoMemory : s = "no memory"; break;
                   case AG_MakeLib  : s = "MakeLib"; break;
                   case AG_OpenLib  : s = "OpenLib"; break;
                   case AG_OpenDev  : s = "OpenDev"; break;
                   case AG_OpenRes  : s = "OpenRes"; break;
                   case AG_IOError  : s = "IO error"; break;
                   case AG_NoSignal : s = "no signal"; break;
                   default          : s = "unknown error"; break;

                   }  /* general */

         }  /* specific */

   /***** Print it out *****/

   fputs (o,stdout);
   fputs (": ",stdout);
   fputs (s,stdout);
   fputs (".\n",stdout);
}

stch_i(st,lg)
char	*st;
unsigned long *lg;
{
char	ch;
short	i,digit;
unsigned long total;
	total = 0;
	for(i=0;i<strlen(st);i++){
		ch = *(st+i);
		if((ch >= 'A') && (ch <= 'F'))
			digit = (short)ch - 55;
		else{
			if((ch >= 'a') && (ch <= 'f'))
				digit = (short)ch - 87;
			else{
				if((ch >= '0') && (ch <= '9'))
					digit = (short)ch - 48;
				else
					return(0);
			}
		}
		total = 16 * total + digit;
	}
	*lg = total;
	return(1);
}
