/* Prg: GURU
	Autor: Stefan Kebekus
	(c) MAXON Computer GmbH 1989
	KICKSTART 1989
*/

#include <exec/types.h>
#define set 0
#define unset 1

/* Texte: Wo ist der Fehler aufgetreten? */
char *Library_Tab[10] =
  {
	"exec",
	"graphics",
	"layers",
	"intuition",
	"math",
	"clist",
	"dos",
	"ram",
	"icon",
	"expansion"
  };

char *Device_Tab[6] =
  {
	"audio",
	"console",
	"gameport",
	"keyboard",
	"trackdisk",
	"timer"
  };

char *Resource_Tab[3] =
  {
	"CIA",
	"Disk",
	"Miscellaneous"
  };

char *Misc_Tab[3] =
  {
	"beim Booten",
	"in der Workbench",
	"während DiskCopy lief"
  };

/* Texte: Was für ein Fehlertyp lag vor? */
char *Class_Tab[6] =
  {
	"eine Library nicht aufgebaut werden konnte",
	"eine Library nicht geöffnent werden konnte",
	"ein Device nicht geöffnet werden konnte",
	"die Hardware nicht reagierte",
	"ein I/O-Fehler auftrat",
	"I/O-Einrichtungen fehlten"
  };

/* Texte: Was für ein Fehler war es genau? */
char *Exec_Tab[10] =
  {
	"Es trat ein Prüfsummenfehlers bei einer CPU-Exeception auf",
	"Es trat ein Prüfsummenfehlers der Startadresse auf",
	"Es trat ein Prüfsummenfehlers einer Library auf",
	"Es war nicht genug Speicher für eine Library vorhanden",
	"Es wurde ein Fehlerhafter Speicherlisteneintrag gefunden",
	"Es war nicht genug Speicher für einen Interrupt vorhanden",
	"Es trat ein Zeiger-Fehler auf",
	"Es wurde ein fehlerhafter Semaphore gefunden",
	"Ein Speicherbereich wurde zum zweiten mal freigegeben",
	"Ein Zeiger-Fehler trat bei einer Exception auf"
  };

char *Graphics_Tab[13] =
  {
	"die Copper-Liste",
	"die Copper-Instructions-Liste vorhanden war",
	"einen neuen Copper-Listeneintrag in der Copperliste",
	"eine Aufteilung der Copper-Liste",
	"den Copper-Listen-Kopf",
	"einen 'long frame'",
	"einen 'short frame'",
	"die Fill-Routine",
	"die Text-Routine",
	"die BlitterBitMap",
	"Es wurde ein falscher Speicherbereich angegeben",
	"das Einrichten eines ViewPorts",
	"einen Zwischenspeicher (GfxNoLCM)"
  };

char *Intuition_Tab[16] =
  {
	"Es wurde ein unbekannter Gadget-Typ angegeben",
	"trat ein Typenfehler bein AN_Gadet auf",
	"die Erstellung eines Ports",
	"ein Menü",
	"ein Untermenü",
	"die Menüleiste",
	"In der Menüleiste ist eine falsche Position",
	"OpenScreen()",
	"die Erstellung eines RastPorts",
	"Es wurde ein unbekannter SCREEN_TYPE benutzt",
	"ein Gadget",
	"ein Window",
	"Es war ein falscher Wert im USR, als Intiuiton geöffnet wurde",
	"kam eine falschen Message über den IDCMP",
	"den Message-Stack",
	"das Console.Device"
  };

char *Dos_Tab[12] =
  {
	"Es gab nicht genug Speicher beim StartUp",
	"Ein Task wurde nicht beendet",
	"Es tart ein Qpkt-Fehler auf",
	"Ein Datenpaket wurde nicht erwartet",
	"Ein freier Zeiger war nicht erreichbar",
	"Es waren fehlerhafte Daten in einem Disk-Block",
	"Die BitMap ist zerstört",
	"Der Key wurde schon freigegeben",
	"Die Prüfsumme war fehlerhaft",
	"Es trat ein Diskettenfehler auf",
	"Ein Key lag außerhalb des erlaubten Bereiches",
	"Es wurde falsch überschrieben"
  };

char *Trackdisk_Tab[2] =
  {
	"Während des Suchens trat ein Fehler auf",
	"Beim Timer-Impuls trat eine Verzögerung auf"
  };

char *Timer_Tab[2] =
  {
	"Es wurde fehlerhaft auf das Device zugegriffen",
	"Durch Netzschwankungen trat ein Fehler bei der Zeikoordinierung auf"
  };

char *Disk_Tab[2] =
  {
	"Die eingelegte Diskette wurde nicht erkannt",
	"Es war kein Laufwerk angeschlossen"
  };

char *Trap_Tab[10] =
  {
	"Es trat ein Daten- oder Adreßbus-Fehler beim Takten auf",
	"Es trat ein Adressierungsfehler (ungerade Adresse) auf",
	"Es trat eine ungültige Instruktion auf",
	"Es trat eine Division durch 0 auf",
	"Es trat eine CHR Instruktion auf",
	"Es trat eine TRAPV Instruktion auf",
	"Es trat eine Privileg-Verletzung auf",
	"Der Prozessor war im Einzelschrittmodus",
	"Es trat ein Line A Befehl auf",
	"Es trat ein Line F Befehl auf"
  };


/* Hauptprogramm */
main(argc,argv)

int	 argc;
char *argv[];

{
UBYTE System,Error_Class,Gadget;
UWORD Error_Code;
LONG	Addresse;
BYTE *String,Og;
char	*arg;
BYTE	flag	= unset;

/* Auf "?" als Parameter reagieren */
	arg			= argv[1];

	if ((arg[0] == '?') || (argc > 2))
	  {
		printf("\nGuru - Wertet Guru-Fehlermeldungen aus.\n");
		printf("© 1988 by Stefan Kebekus\n\n");
		printf("Gebrauch: Guru Gurunummer\\a\n");
		exit(0);
	  }

/* Wurde eine Guru-Nummer angegeben? */
if (argc == 2)
  {							/* Ja, also */
	System		= htoi(arg[0])*16  +htoi(arg[1]);	/* Die angegebene Ziffer zerlegen */
	Error_Class = htoi(arg[2])*16  +htoi(arg[3]);
	Error_Code	= htoi(arg[4])*4096+htoi(arg[5])*256+
					  htoi(arg[6])*16  +htoi(arg[7]);

	if (arg[8] != 0)					/* ...falls zuviele Stellen */
	  {							/* angegeben wurden... */
		printf("Bitte 8 Stellen ! (Das waren zuviel !)\n");
		exit(0);
	  }

	flag			= set;
  }
else
  {							/* Falls keine Guru-Nummer angegeben wurde, */
	System		= (UBYTE) *((UBYTE *) 0x100L);		/* werden die Zahlen aus dem Speicher geholt */
	Error_Class = (UBYTE) *((UBYTE *) 0x101L);
	Error_Code	= (UWORD) *((UWORD *) 0x102L);
	Addresse 	= (LONG ) *((LONG  *) 0x104L);

/* 1. Meldung machen: Guru-Nummer & Adresse ausgeben */
	printf("\nGuru-Nummer: %02x%02x%04x.%08lx\n\n",System,Error_Class,Error_Code
													  ,Addresse);

  }

Gadget = (System & 0x70) / 16;
System = System & 0x7f;

/* Error-Code korrigieren */
switch (System)			/* Testen, in welchem Teilsystem des Betriebssystems */
{				/* der Fehler aufgetreten ist. */
 case 0: String = Trap_Tab[Error_Code-=2];	/* Trap_Tab */
			Og 	 = 9;
			break;

 case 1: if (Error_Code > 0) Error_Code--;	/* Exec */
			String = Exec_Tab[Error_Code];
			Og 	 = 9;
			break;

 case 2: Error_Code--;							 /* Graphics */
			if (Error_Code == 0x2f)   Error_Code = 11;
			if (Error_Code == 0x1233) Error_Code = 12;
			String = Graphics_Tab[Error_Code];
			if (Error_Code == 10) Error_Class = 0;
			Og 	 = 12;
			break;

 case 3: String = (char *)"die Layers";
			Error_Class = 1;
			Og 	 = 0;
			break;

 case 4: String = Intuition_Tab[Error_Code];
			Og 	 = 15;
			if (Error_Code > 13) Error_Class = 1;
			break;

 case 7: Error_Code--;
			String = Dos_Tab[Error_Code];
			Og 	 = 11;
			break;

 case 8: String = (char *)
			"In der Verwaltungsliste ist ein fehlerhafter Eintrag";
			Og 	 = 0;
			break;

 case 0xa: String = (char *)
			  "In der Erweiterung der Hardware ist ein Fehler";
			  Og		= 0;
			  break;

 case 0x14: Error_Code--;
				String = Trackdisk_Tab[Error_Code];
				Og 	 = 1;
				break;

 case 0x15: Error_Code--;
				String = Timer_Tab[Error_Code];
				Og 	 = 1;
				break;

 case 0x21: Error_Code--;
				String = Disk_Tab[Error_Code];
				Og 	 = 1;
				break;

 case 0x30: String = (char *)
				"Beim Auswerten der Boot-Daten ist ein Fehler aufgetreten";
				Og 	 = 0;
				break;

 default:	if (Error_Class == 1) String == (char *)"???";
				 else
				String == (char *)" ";
				break;
}

System = System & 0x0f;

if ((Error_Code < 0) || (Error_Code > Og ))
  {
	printf("Das System war so durcheinander, daß der Fehler unvollständig\n");
	printf("oder falsch klassifiziert ist.\n");
	String = (char *)"???";
  }

if ((System | Gadget) == 0) Gadget = 4;

/* Meldung als ganzen Satz ausgeben */
printf("Der Fehler trat ");
if (Gadget == 0) printf("in der %s.library auf",Library_Tab[System-1]);
if (Gadget == 1) printf("im %s.device auf",Device_Tab[System]);
if (Gadget == 2) printf("der %s-resource auf",Resource_Tab[System]);
if (Gadget == 3) printf("%s auf",Misc_Tab[System]);
if (Gadget == 4) printf("in Ihrem Programm auf");

/* Welcher String darf es sein ? */

switch (Error_Class)
{
 case 0: printf(".\n");
			break;

 case 1: printf(", weil nicht genug Speicher \nfür %s vorhanden war.\n\n"
						,String);
			break;

 default: printf(",\nweil %s.\n",Class_Tab[Error_Class-2]);
			 break;
}

if (Error_Class != 1) printf("%s.\n\n",String);
if (flag == unset) printf("Der Fehler lag im Speicher bei $%lx.\n",Addresse);

}

/* Unterroutine zum Umwandeln ASCII->Hex */
htoi(z)

char z;
{
int i;

 if (z == 0)
	{
	 printf("Bitte 8 Stellen !  (Das waren zuwenig !)\n");
	 exit(0);
	}

 if (z > '9')
	i= z - 'a' + 10;
 else
	i= z - '0';

	if (i > 15)
	  {
		printf("Nur Hex-Ziffern verwenden !\n");
		exit(0);
	  }
 return(i);
}

