\section{Der Debugger ({\tt m2debug})}

Wenn man ein Modula-2 Programm schreibt, kann man im wesentlichen zwei
Arten von Fehlern machen: {\bf Syntaktische Fehler} und
{\bf semantische Fehler}.
Die syntaktischen Fehler werden alle durch den Compiler gefunden; also
wenn man ein Komma oder Strichpunkt an der falschen Stelle geschrieben
hat, wenn man ein reserviertes Wort falsch geschrieben hat oder wenn man
sich sonst nicht an die Modula-2 Syntax gehalten hat.

Bei den semantischen Fehlern k"onnen wir wiederum zwei weitere Arten
unterscheiden: Die semantischen Fehler, die der Compiler bereits beim
"Ubersetzen entdecken kann; dies w"aren beispielsweise nicht deklarierte
Variablen oder Typenunvertr"aglichkeiten. Und die zweite Art sind die
semantischen Fehler, die der Compiler nicht herausfinden kann, weil
sie dynamische Vorg"ange betreffen; als Beispiel k"onnte man hier
"Uberschreiten der Feld-Grenzen, Zugriff auf Zeigervariablen mit
dem Wert {\tt NIL} oder Zuweisung eines negativen Wertes an eine
{\tt CARDINAL}-Variable anf"uhren.

Genau diese zweite Art der semantischen Fehler ist aber die gemeine,
welche die Logik des Programms ausmacht. Diese Fehler entscheiden meist
dar"uber, ob ein Programm l"auft oder nicht. Unser Compiler {\tt m2c}
erzeugt nun zus"atzliche Instruktionen im Programm, um diese "`Fehler
der zweiten Art"' abzudecken.

So weit so gut. Nun taucht so ein gemeiner Fehler auf, und das Programm
bricht mit einer Fehlermeldung ab. Das ist zwar schon ein Fortschritt
gegen"uber dem allseits beliebten "`Guru"', aber immer noch weit entfernt von
Benutzerfreundlichkeit. Die Fragen, die Sie sich jetzt klarerweise stellen,
sind:

\begin{itemize}
\item
  {\em Wo\/} ist mein Programm abgest"urzt?
\item
  {\em Wie\/} sieht die Variablen-Belegung im Zeitpunkt des Abbruchs aus?
\item
  {\em Was\/} passierte vorher?
\end{itemize}


\subsubsection{Was kann unser Debugger?}

Der Debugger nun ist ein Werkzeug, der diese Art von Fehler lokalisieren
kann. Er kann die Stelle anzeigen, wo der Fehler aufgetaucht ist, und was
fast wichtiger ist, er zeigt auch die Umgebung, in welcher der Fehler
aufgetaucht ist. Meist l"auft n"amlich eine programmierte Prozedur in 95
Prozent aller F"alle korrekt, und nur unter ganz bestimmten Bedingungen
l"auft etwas schief. Diese Bedingungen sind aber dynamisch, das heisst
sehr von der momentanen Umgebung beziehungsweise vom Zeitpunkt abh"angig,
in der die Prozedur aufgerufen wird.

Unser Debugger ist vom Typ her ein {\bf post-mortem Debugger}. Dies bedeutet,
dass er erst nach dem "`Tod"', nach dem Absturz des Programms, aufgerufen
wird. Man kann mit ihm also nicht direkt w"ahrend des Ablaufs des
Programms alle Variablen anschauen oder sogar ver"andern: dies w"are die
Aufgabe eines Runtime-Debuggers.

Unser Debugger zeigt die Fehlerstelle aber direkt im Programmtext an.
Der Benutzer braucht sich also nicht mit der Maschinensprache des
Prozessors oder mit dessen Registern herumzuplagen. Die Adresse der
Fehlerstelle wird nicht direkt als Adresse im Hauptspeicher ausgegeben,
sondern in einem ersten Schritt auf das \mtwo\ Modul eingeschr"ankt
und dann auf die Prozedur und genaue Anweisung verfeinert.

Ausserdem muss man sich mit dem Amiga Modula-2 Debugger bei der
Programmierung eigener Programme nicht um den Debugger k"ummern. Jedes
Programm kann von den Fehlern befreit werden,
ohne dass spezielle  Break-Points gesetzt,
oder gar Code-"Anderungen gemacht werden.





\subsection{Aufruf und Bedienung}

Der jetzige Debugger ist im Gegensatz zu fr"uheren Versionen als
{\bf Hintergrundprozess} programmiert, der von einem Modula-2 Programm
im Fehlerfalle aktiviert werden kann. Man l"adt ihn in den Speicher
mit einem Doppelklicken seiner Ikone oder einer Anweisung wie

\begin{quote}\tt
run m2debug
\end{quote}

Hat man ihn so als DOS-Prozess gestartet, "`schl"aft"' er, bis er aufgeweckt
wird. Wenn eines Ihrer Modula-2 Programme abst"urzt, erhalten Sie
einen Requester mit der Fehlerursache und den beiden Auswahlfeldern:
"`{\tt debug}"' und "`{\tt abbrechen}"'. Sp"atestens jetzt sollte
man den Debugger aufstarten!%
\footnote{Das vorherige Aufstarten hat den Vorteil, dass der Debugger
sicher die notwendigen Ressourcen erh"alt, unabh"angig davon,
wie sich danach das fehlerhafte Programm verh"alt.}
Wenn Sie nun "`{\tt debug}"' w"ahlen, dann tritt
{\tt m2debug} in Aktion. Wenn Sie "`{\tt debug}"' w"ahlen,
aber gar kein Debugger
im System vorhanden ist, dann passiert nichts.

Der Debugger "offnet einen eigenen Screen, auf dem dann f"unf Fenster
mit verschieden Daten pr"asentiert werden. Der genaue Inhalt der
einzelnen Fenster ist im n"achsten Abschnitt beschrieben.
Die Gr"osse und Eigenschaften des Screens holt sich der Debugger vom
Workbenchscreen. So ist beispielsweise auf einem Amiga 3000 auch der
Debugger-Screen im "'productivity mode"', wenn die Workbench in diesem
Modus arbeitet. Die gesamte Benutzeroberfl"ache des Debuggers bedient
sich der gebr"auchlichen Amiga Ein- und Ausgabe: Maus, Fenster, Menus,
String-Requester.

\begin{note}
Sie k"onnen mit der rechten Maustaste
ebenfalls selektieren, wie Sie es mit der linken Maustaste gewohnt sind.
Weil der Amiga aber normalerweise den rechten Mausknopf f"ur die Menus
reserviert hat, d"urfen Sie sich durch den oben eingeblendeten Menubalken
nicht irritieren lassen, solange Sie den rechten Mausknopf gedr"uckt haben.
Beim Loslassen des rechten Knopfes reagiert der Debugger wie erwartet.
\end{note}

Um "`{\tt m2debug}"' wieder aus dem Speicher zu entfernen, rufen Sie 
einfach das Kommando "`{\tt killm2debug}"' auf. 





\subsection{Die Fenster}

Nachdem der Debugger aktiviert wurde, sehen Sie f"unf Fenster auf dem
Bildschirm. In jedem Fenster sehen Sie bestimmte Daten, deren Bedeutung
nachfolgend erkl"art wird. In den Erkl"arungen verweisen wir immer wieder
auf den n"achsten Abschnitt \ref{Menu} "`Die Menus"'; die meisten Menus haben
n"amlich nur Einfluss auf ein Fenster.

Sie k"onnen die Fenster nach Belieben in Gr"osse und Position ver"andern.
Die minimale Fenstergr"osse ist so gew"ahlt, dass mindestens noch eine
Datenzeile im Fenster sichtbar ist. Wenn Ihnen Ihr Layout gef"allt,
bietet der Debugger auch eine M"oglichkeit, Ihre Fenster-Anordnung
abzuspeichern (siehe Menu "`Layout"'). Das n"achste Mal startet dann
der Debugger mit der abgespeicherten Anordnung.

Auf dem Amiga ist es "ublich, dass am rechten Rand ein Balken erscheint,
mit dem man im Fenster bl"attern kann. Diese M"oglichkeit nimmt der
Debugger immer dann in Anspruch, wenn er mehr Daten im Fenster darstellen
will, als momentan Platz haben.

\begin{note}
Der Zeichensatz, mit dem der Debugger die
Fenster"-"uber\-schrif\-ten und den Fensterinhalt schreibt,
ist der vom System vorgegebene Zeichensatz (system default font).
Ab Workbench 2.0 k"onnen Sie diesen Zeichensatz auch "andern,
wenn Sie wollen.
\end{note}


\subsubsection{Quelltext}

In diesem Fenster wird der Modula-2 Text eines Moduls dargestellt. Am
Anfang zeigt der Debugger in diesem Fenster invers dargestellt die
Fehlerstelle, an der das Programm abgebrochen wurde. Sie k"onnen in
dieses Fenster auch Texte anderer Prozeduren und Module laden lassen,
indem Sie in den Fenstern {\tt Aufrufkette}
oder {\tt Module} mit der Maus klicken.

\begin{itemize}
\item
  linker/rechter Mausknopf: keine Bedeutung
\item
  verwandte Menus: "`{\tt .def}"', "`{\tt .mod}"' und
  "`{\tt Quelltext}"'
\end{itemize}

Wenn der Debugger keine entsprechende {\tt .mod}-
beziehungsweise {\tt .def}-Datei
finden kann, erscheit stattdessen auf der ersten Zeile 
die Meldung "`{\tt -- kein Quelltext vorhanden}"'.


\subsubsection{Aufrufkette}

In diesem Fenster ist die Prozeduraufrufkette sichtbar. Sie k"onnen
hier genau sehen, in welcher Reihenfolge die Prozeduren bis zum
Laufzeitfehler aufgerufen wurden. Dabei steht die Prozedur, in der Ihr
Programm abgebrochen oder unterbrochen wurde,
zuoberst im Fenster. Die darunterstehende
Prozedur hat diese aufgerufen und so weiter.

Auf der allerersten Zeile dieses Fensters sehen Sie die Fehlermeldung,
mit der Ihr Programm abgebrochen wurde. Im Falle eines {\tt Assert}s oder
eines {\tt BreakPoint}s aus dem Modul {\tt Arts}, steht hier der Text,
den Sie als Parameter angegeben haben.

In der ersten Spalte steht der Prozedurname. Diesen kann der Debugger
aber nur herausfinden, falls er eine entprechende
{\tt .ref}-Datei des Moduls
finden konnte. In einer zweiten Spalte steht der Modulname.

\begin{itemize}
\item linker Mausknopf: die lokalen Daten der angeklickten Prozedur
erscheinen in einem der Daten-Fenster.

\item rechter Mausknopf: die Stelle im Programmtext, wo die Prozedur
aufgerufen wurde, wird im Quelltext-Fenster invertiert angezeigt.

\item verwandte Menus: "`{\tt Prozeduren}"'
\end{itemize}


\subsubsection{Modultabelle}

In diesem Fenster sind alle Moduln, die Ihr Programm ben"otigt, aufgelistet.
In der ersten Spalte steht eine interne Laufnummer, in der zweiten Spalte
der Modulname und in der dritten Spalte die Anfangsadresse des Moduls.
Moduln {\em ohne\/} Implementation sind davon ausgenommen und
erscheinen {\em nicht\/} in der Modultabelle.

\begin{itemize}
\item linker Mausknopf: die globalen Daten des angeklickten Moduls
erscheinen in einem der Daten-Fenster.

\item rechter Mausknopf: es wird das Definitions- oder Implementations-
Modul im Quelltext-Fenster angezeigt. 

\item verwandte Menus: "`{\tt .def}"', "`{\tt .mod}"'
  und "`{\tt Module}"'
\end{itemize}


\subsubsection{Daten 1 und 2}

In diesen Fenstern werden die Variablen dargestellt, und zwar Name,
Wert und Typ der Variablen. Da die Informationen sehr vom Typ der
Variablen abh"angen, haben wir f"ur genauere Informationen, {\em was\/} der
Debugger in {\em welchen\/} F"allen {\em wie\/} darstellt,
einen eigenen Abschnitt eingef"ugt
(siehe \ref{Typen} "`Darstellung der Daten"').

Welche Daten in den Fenstern erscheinen sollen, k"onnen Sie mit den
Menupunkten "`{\tt Moduln}"' und "`{\tt Prozeduren}"' angeben.
Normalerweise stellt
der Debugger im Fenster "`{\tt Daten 1}"' die lokalen
Daten der Prozedur dar, und
in "`{\tt Daten 2}"' werden die globalen Daten des Moduls gezeigt.

Wenn Sie in eine Datenstruktur "`hineinzoomen"', zeichnet der Debugger
in der obersten Zeile des Fensters den Weg auf, wie man zum jetzigen
Punkt gelangt ist. Durch Anklicken in dieser Zeile kann man wieder zu
einem fr"uheren Punkt zur"uckgehen, also z.B. in Falle von

\begin{quote}
\verb'intuiBasePtr^.activeWindow^.wScreen^.rastPort.bitMap^'
\end{quote}

kann man durch Anklicken mit der linken Maustaste von
{\tt wScreen} wieder zum {\tt Screen}-Zeiger zur"uckkehren.
Die maximale L"ange einer solchen Anzeige einer Datenstruktur
ist auf 512 Zeichen beschr"ankt.

\begin{itemize}
\item linker Mausknopf:
  \begin{itemize}
  \item auf Variable: Zoomen in Datenstruktur
  \item auf oberster Zeile: Zur"uckkehren zu fr"uheren Datenstrukturen
  \end{itemize}

\item rechter Mausknopf: Zuweisung eines neuen Typs zur angeklickten
Variablen (siehe auch \ref{Change} "`Typen "andern"').

\item verwandte Menus: "`{\tt Module}"' und "`{\tt Prozeduren}"' 
\end{itemize}





\subsection{Die Menus}\label{Menu}

{\tt m2debug} bietet gewisse Funktionen, die das Verhalten des Debuggers
beeinflussen. Diese Funktionen sind in Menus gegliedert. Die Menus
rufen Sie wie auf dem Amiga gewohnt mit der Maus auf. Sie fahren mit
der Maus in die linke obere Ecke des Screens und dr"ucken dort die rechte
Maustaste.

\begin{note}
Der Menuzeichensatz ist fest "`{\tt topaz.8}"'. Eine
"Anderung ist vorl"aufig nicht vorgesehen.
\end{note}


\subsubsection{.def, .mod}

Diese zwei, sich gegenseitig ausschliessenden Schalter geben an, ob
beim Laden eines Quelltextes im Source-Fenster das Definitions- oder
Implementationsmodul gezeigt werden soll.

\subsubsection{Moduln}

Dieser Menupunkt enth"alt zwei Unterpunkte: "`{\tt Daten 1}"'
und "`{\tt Daten 2}"'.
Mit diesem Menu k"onnen Sie angeben, in welchem Fenster die globalen
Daten eines Moduls angezeigt werden sollen. Haben Sie beispielsweise
"`{\tt Daten 2}"' gew"ahlt, dann erscheinen die Moduldaten
im Fenster "`{\tt Daten 2}"',
wenn Sie im Fenster "`{\tt Moduln}"' ein Modul anklicken.

\noindent Beim Aufstarten von {\tt m2debug} werden
die Moduldaten in "`{\tt Daten 2}"' dargestellt.


\subsubsection{Prozeduren}

Dieser Menupunkt enth"alt zwei Unterpunkte:
"`{\tt Daten 1}"' und "`{\tt Daten 2}"'. Mit diesem
Menu k"onnen Sie angeben, in welchem Fenster die lokalen Daten einer
Prozedur angezeigt werden sollen. Sie w"ahlen beispielsweise "`{\tt Daten 2}"'.
Wenn Sie jetzt im Fenster "`{\tt Aufrufkette}"' mit dem rechten Mausknopf eine
Prozedur anklicken, erscheinen die
lokalen Variablen im Fenster "`{\tt Daten 2}"'.

\noindent Beim Aufstarten von {\tt m2debug} werden die Prozedurdaten in
"`{\tt Daten 1}"' dargestellt.


\subsubsection{Layout}

Falls Sie die Fenster in der Gr"osse oder ihrer Position ver"andert haben,
k"onnen Sie das momentane Layout abspeichern oder wieder zum alten
zu"-r"uck\-keh\-ren. Bei diesem Menupunkt gibt es zwei Unterpunkte:
"`{\tt Speichern}"' und "`{\tt Laden}"'.
Die Information legt der Debugger in einer Datei ab, die den
Namen {\bf M2:M2Debug.prefs} hat. Da {\tt m2debug} die Anordnung immer
aus dieser Datei liest, falls sie vorhanden ist, k"onnen Sie zur
Original-Anordnung der Fenster wieder zur"uckkehren, indem Sie einfach
diese Datei l"oschen. Speichern und Laden k"onnen "ubrigens auch
mit der rechten Amiga-Taste und "`{\tt S}"' beziehungsweise "`{\tt L}"'
aufgerufen werden.


\subsubsection{Screen}

Mit diesem Menupunkt k"onnen Sie zwischen
vier verschiedenen Bildschirm-Modus umschalten.
Es sind dies
\begin{itemize}
\item Noninterlace 2 Farben
\item Noninterlace 4 Farben
\item Interlace 2 Farben
\item Interlace 4 Farben
\end{itemize}

Im "`Interlace"'-Modus k"onnen Sie doppelt
soviele Zeilen auf dem Bildschirm sehen.
Die Vorgabe ist Noninterlace, 2 Farben. Diesen Menupunkt k"onnen
Sie auch mit der Tastatur aktivieren: rechte Amiga-Taste und "`{\tt I}"'.


\subsubsection{Quelltext}

Gerade bei l"angeren Programmtexten dauert es eine kleine Weile bis
der Debugger die Fehlerstelle im Text lokalisiert hat. Wenn Ihnen diese
Dauer zu lange erscheint, dann k"onnen Sie mit den zwei Unterpunkten
dieses Menus angeben, wie sich {\tt m2debug} verhalten soll: Soll
er den Quelltext immer anzeigen, dann stellen Sie "`{\tt automatisch}"' ein,
wenn er den Quelltext nur auf Verlangen darstellen soll, w"ahlen Sie
den Unterpunkt "`{\tt auf Befehl}"'.


\subsubsection{Ende}

Mit diesem Menupunkt verlassen Sie den Debugger. Er bleibt aber immer
noch als Hintergrundprozess im Speicher geladen. Nur mit dem Befehl
{\tt killm2debug} wird der Debugger endg"ultig aus dem Speicher entfernt.
Dieser Menupunkt l"asst sich auch mit der Tastatur aktivieren: rechte
Amiga-Taste und "`{\tt Q}"'.





\subsection{Darstellung der Daten}\label{Typen}

Die St"arke unseres Debuggers liegt vor allem in der typengerechten
Darstellung der Variablen. Da der Debugger beispielsweise
bei {\tt CARDINAL}s und
bei {\tt ARRAY}s andere Informationen "uber die Variable darstellt, sind in
diesem Abschnitt alle Typen und ihre etwaigen Spezialit"aten aufgef"uhrt.


\subsubsection{Unstrukturierte Typen}

Bei den unstrukturierten Typen stellt der Debugger immer den Wert der
Variablen dar. Die Frage ist nur in welcher Form: dezimal, hexadezimal,
oktal oder ASCII. Nachfolgend sind alle unstrukturierten Typen aufgelistet
und etwaige Besonderheiten der Darstellung erw"ahnt:

\begin{description}
\item[BOOLEAN] Normalerweise pr"asentiert Ihnen der Debugger Variablen
von diesem Typ in der Form TRUE oder FALSE. Nun kann aber bei
un\-ini\-tia\-li\-sier\-ten Variablen ein
ung"ultiger Wert entstehen. {\tt m2debug}
zeigt Ihnen dies an, indem er vor dem hexadezimalen Wert der Variablen
ein Fragezeichen schreibt.

\item[CHAR] Bei Variablen vom Typ {\tt CHAR} gibt es zwei verschiedene
Darstellungen: entweder wird der Buchstabe ASCII-m"assig ausgegeben,
oder - falls er keine brauchbare ASCII-Umsetzung hat - oktal in der
ge"-br"auch\-li\-chen \mtwo\ Schreibweise mit einem angeh"angten C (z.B. 205C)

\item[Ganze Zahlen] F"ur den Bereich der ganzen Zahlen existieren in
Amiga Modula-2 sechs verschiedene Typen, die sich nur in Gr"osse und
Vorzeichenbehandlung unterscheiden: {\tt SHORTCARD}, {\tt CARDINAL},
{\tt LONGCARD},
{\tt SHORTINT}, {\tt INTEGER} und {\tt LONGINT}.
Bei allen Variablen dieser Typen wird
der Inhalt dezimal dargestellt.

\item[Gleitpunkt-Zahlen] In Amiga Modula-2 gibt es drei verschiedene Typen,
wie Gleitpunkt-Zahlen deklariert sein k"onnen: {\tt REAL},
{\tt LONGREAL}, {\tt FFP}.
Normalerweise wird der Wert
der Variablen in Exponential-Schreib\-wei\-se gezeigt.
Nun kann die Variable aber ung"ultige Bitmuster enthalten, die
keine korrekte Gleitpunkt-Zahl darstellen. In diesem Fall wird der Inhalt der
Variable hexadezimal angezeigt.

\item[Unterbereich] F"ur Variablen eines Unterbereichs gilt das gleiche
wie f"ur Variablen der Typen {\tt CARDINAL} oder {\tt INTEGER}:
Der Wert wird dezimal angezeigt.

Wenn Sie bei der Deklaration einer Variablen unmittelbar
den Unterbereich angeben,
dem Typ also keinen eigenen Namen geben (z.B. {\tt VAR i:\ [-5..5];}),
dann schreibt der Debugger beim Typnamen das Wort {\tt INTBASE}.

\item[Aufz"ahlung] Bei Aufz"ahlungstypen wird der Wert der Variablen
vom Debugger automatisch mit dem richtigen Namen angegeben. Falls der
Wert zu gross ist, wie dies bei uninitialisierten Variablen vorkommen
kann, wird der aktuelle Wert hexadezimal ausgegeben, und vor dem Wert
steht ein Fragezeichen.

Ist bei einer Variablendeklaration f"ur den Typ direkt eine Aufz"ahlung
angegeben, hat dieser Aufz"ahlungstyp keinen Namen.
Eine solche Deklaration ---  also z.B. {\tt VAR tag:\ (so,\ mo,\ %
di,\ mi,\ do,\ fr,\ sa);}\ --- f"uhrt beim Debugger beim Typnamen zur
Ausgabe {\tt ENUMERATION}.
\end{description}


\subsubsection{Strukturierte Typen}

Bei den strukturierten Typen kann der Debugger nicht auf einmal den
ganzen Wert der Variablen darstellen. Deshalb zeigt der Debugger oft
nur die Gr"osse oder die Anfangsadresse. Er bietet aber eine komfortable
M"oglichkeit in die Struktur der Variablen vorzustossen.

Immer wenn der Debugger noch mehr Informationen zu einer Variablen hat,
schreibt er in einer Spalte hinter dem Variablennamen ein Sternchen. Dies
bedeutet, dass man mit der Maus die Variable anklicken kann. Der Debugger
zoomt dann in die Struktur hinein. Nach diesem Prinzip ist es m"oglich, auch
komplizierteste Datenstrukturen einfach durchzubl"attern.

Auch hier folgt wieder eine Liste aller m"oglichen Typen
und eine Auf"-z"ah\-lung ihrer Besonderheiten:

\begin{description}
\item[ARRAY] Bei den {\tt ARRAY}s wird als Wert die Gr"osse in Byte angegeben.
Statt der Gr"osse kann auch das Wort "`{\tt (dyn)}"' stehen, wenn die Variable
ein Prozedurparameter ist, der als {\tt ARRAY OF ...} deklariert wurde.
Bei Feldern schreibt {\tt m2debug} --- wie in der Einleitung erkl"art ---
ein Sternchen (*) hinter den Variablennamen. So wissen Sie, dass Sie die
Variable anklicken k"onnen;
sie erhalten dann eine Liste aller {\tt ARRAY}-Elemente.

\item[RECORD] Bei den {\tt RECORD}s wird als Wert die Gr"osse
in Byte angegeben.
Auch hier erscheint ein Sternchen (*) hinter dem Variablennamen, damit Sie
nach einem Anklicken der Variablen eine Liste aller
{\tt RECORD}-Felder bekommen.
In \mtwo\ ist es m"oglich, verschiedene Felder in einem {\tt RECORD} an die
gleiche Adresse zu legen, um Speicherplatz f"ur Varianten zu sparen.
Im folgenden Beispiel sind die Felder "`{\tt anzahlTasten}"'
und "`{\tt fellFarbe}"'
am gleichen Ort im Speicher:

\begin{verbatim}
TYPE
 Farbe = (grau, weiss, schwarz, braun);
 MausInfo = RECORD
   CASE computerMaus: BOOLEAN OF
   | TRUE:  anzahlTasten: INTEGER
   | FALSE: fellFarbe: Farbe
   END
 END;
\end{verbatim}

Um Ihnen auch bei den Varianten-{\tt RECORD}s Anhaltspunkte zu liefern, wo
ein Feld ein anderes "uberlagert, schreibt {\tt m2debug} vor den Namen
solcher Felder ein Copyright-Zeichen ($\copyright$).
Das "`c"' des Copyright-Zeichens soll an das Wort {\tt CASE} erinnern.

\item[SET] Bei einem {\tt SET} wird der Wert hexadezimal ausgegeben. Da das
auf"-z"ah\-len aller gesetzten {\tt SET}-Elemente mehr Platz
als eine Zeile ben"otigt,
erscheint auch hier ein Sternchen (*). Sie k"onnen sich die
einzelnen Elemente im {\tt SET} anzeigen lassen,
indem Sie die Variable anklicken.
Das gleiche gilt auch f"ur die vordefinierten \mtwo\ Typen {\tt BITSET},
{\tt SHORTSET} und {\tt LONGSET}.

\item[POINTER] Der Wert einer Variablen vom Typ {\tt POINTER} oder
{\tt BPOINTER} ist eine
Adresse im Speicher, auf welche die Variable zeigt. Diese Adresse wird
hexadezimal ausgegeben, oder {\tt m2debug} schreibt im Fall von 0 {\tt NIL}.
Durch Anklicken der Variablen --- sie ist demnach mit einem Sternchen (*)
gekennzeichnet --- k"onnen Sie weiter in die Datenstruktur vorstossen.

Anders ist dies bei Variablen eines opaken Typs. In diesem Fall schreibt
der Debugger anstelle eines Wertes das Wort "`{\tt (opaque)}"'
und Sie k"onnen die
Variable {\em nicht\/} anklicken.
Weiter ist auch bei allen Variablen der Typen
{\tt ADDRESS} und {\tt BPTR} das Anklicken nicht m"oglich.
{\tt m2debug} bietet
Ihnen aber die M"oglichkeit, den Typ zu "andern (siehe Abschnitt \ref{Change}
"`Typen "andern"')

\item[PROC] Sowohl bei Variablen eines selbstdeklarierten
{\tt PROCEDURE}-Typs als auch beim Typ {\tt PROC} zeigt
Ihnen unser Debugger als
Wert die Anfangsadresse der Prozedur in hexadezimaler Form. Ein Anklicken
ist nicht m"oglich!
\end{description}

\begin{warning}
Die Darstellung der Daten kann in wenigen F"allen unangenehme
Folgen haben: so darf die {\tt RECORD}-Variable {\tt Hardware.Custom}
{\em nicht\/} im Debugger angeschaut werden, da gewisse
Elemente auf blossen Zugriff reagieren. Ein Absturz ist damit
garantiert! Zwar erscheint das Modul {\tt Hardware} als
implementationsloses Modul nicht in der Modultabelle, aber es
lassen sich in eigenen Moduln problemlos Zeiger auf 
{\tt Hardware.Custom} deklarieren. 

\end{warning}



\subsection{Typen "andern}\label{Change}

In unserem Debugger ist es m"oglich, den Typ einer Variablen durch
einen anderen zu ersetzen. Im Prinzip entspricht es der Funktion
{\tt CAST} im Compiler, wobei aber "`{\tt m2debug}"' restriktiver vorgeht:

\begin{itemize}
\item Es sind nur Variablen folgender Zeiger-Typen zul"assig:
{\tt POINTER} auf beliebige Objekte,
{\tt ADDRESS}, {\tt BPOINTER}, {\tt BPTR} und opake Typen
\item Eine "Anderung ist nur m"oglich, falls die Variable nicht den Wert
{\tt NIL} hat 
\end{itemize}

Dazu klicken Sie mit der rechten Maustaste eine Variable an. Danach
erscheint ein Eingabefeld, in dem {\tt m2debug} einen Namen eines Typs
erwartet. Haben Sie aus Versehen die rechte Maustaste gedr"uckt,
geben Sie einfach nichts ein und schliessen mit der \keyret-Taste ab.
Wollen Sie hingegen den Typ "andern, m"ussen Sie den Namen eines bestehenden
Typs eingeben. Dieser Name setzt sich aus zwei Teilen zusammen: zuerst
das Modul, wo {\tt m2debug} den Typ suchen soll. Dann durch Punkt getrennt,
der Typname. Der verwendete Modulname muss dabei in der
Modulliste vorhanden sein. Ausserdem bietet das Modul {\tt Arts}
einen Typ
\begin{quote}\tt
StrPtr = POINTER TO ARRAY [0..63] OF CHAR;
\end{quote}
an, der bei nur als {\tt ADDRESS} deklarierten Zeichenketten verwendet werden
kann. Beispiel einer Umwandlung:

\begin{quote}\tt
DosL.ProcessPtr
\end{quote}

\begin{note}
Neuerdings sind bei den Library-Moduln die Prozeduren
und die Datenstrukturen in zwei verschiedene Moduln aufgeteilt; so sind zum
Beipiel die Typen in {\tt DosD} und die Prozeduren in {\tt DosL}.
Im Debugger muss f"ur die Typen"anderung {\em immer\/} der Typ
via {\cmsltt Modul\tt L} angesprochen werden, also in unserem Beispiel
qualifiziert aus dem Modul {\t DosL}.
\end{note}


\subsubsection{Beispiele}

Hier wollen wir die Leistungsf"ahigkeit dieses Befehls an zwei typischen
Beispielen demonstrieren:

Nehmen wir an, dass Sie irgendwo in ihren Intuition Strukturen eine
Variable {\tt g:\ Gadget;} haben. Sie wollen nun im Debugger anschauen,
mit welchen Daten Intuition dieses Gadget zeichnet. Das Problem ist
aber, dass das Feld {\tt g.gadgetRender} vom Typ {\tt ADDRESS} ist.
Im Prinzip zeigt dieses Feld auf eine Border- oder Image-Struktur.
Welche Struktur Intuition zum Zeichnen verwendet, steht im Feld
{\tt g.flags}. Als erstes schauen wir im Feld {\tt g.flags} nach,
ob das Bit {\tt gadgImage} gesetzt ist. Nehmen wir an, es sei nicht
gesetzt; dies bedeutet, dass {\tt g.gadgetRender} auf eine Border-
Struktur zeigt. Nun k"onnen wir den Typ "andern.

Klicken Sie nun das Feld {\tt g.gadgetRender} mit dem rechten Mausknopf
an. Es erscheint ein Eingabefeld, in das Sie {\tt IntuitionL.BorderPtr}
schreiben. Nachdem Sie Ihre Eingabe mit \keyret\ best"atigt haben, ist
das Feld {\tt g.gadgetRender} vom Typ {\tt BorderPtr}. Sie k"onnen nun
in die Struktur hineinzoomen.

F"ur unser zweites Beispiel nehmen wir folgendes an: Sie schreiben ein
Modul, dass mit beliebig langen Zahlen rechnen kann. Dazu deklarieren
Sie in der Definition Ihres Moduls {\tt SuperREAL:~TYPE MyREAL;}. Dies
ist eine opake Typendeklaration; nur in der Implementation ist bekannt,
wie der Typ {\tt MyREAL} aussieht. Nun ist das solange eine gute Idee,
bis Sie Ihr Modul austesten wollen und eventuell auch in die Daten Ihrer
Struktur hineinschauen wollen. Der Debugger wird sich aber leider
weigern, eine Variable "`{\tt VAR r:~MyREAL;}"' Ihres Testprogramms n"aher
zu zeigen.

Da Sie aber die Referenzdatei des Moduls {\tt SuperREAL} besitzen, k"onnen
Sie den opaken Typ aufl"osen und ihn in {\tt SuperREAL.MyREAL} verwandeln.
Dann wird der Debugger alle Daten Ihrer Variablen {\tt r} darstellen
k"onnen.





\subsection{Ein vollst"andiges Beispiel}

Betrachten wir folgendes Beispielprogramm:

\begin{verbatim}
MODULE test;

FROM Heap IMPORT Allocate;

TYPE
 String = ARRAY [0..5] OF CHAR;
 NodePtr = POINTER TO Node;
 Node = RECORD
  next: NodePtr;
  id: LONGINT;
  data: String
 END;

VAR
 list: NodePtr;

PROCEDURE CopyString(in: ARRAY OF CHAR;
                     VAR out: ARRAY OF CHAR);
 VAR i: INTEGER;
 BEGIN
  FOR i:=0 TO HIGH(in) DO out[i]:=in[i] END;
  out[HIGH(in)+1]:=0C
 END CopyString;

PROCEDURE AddNode(id: LONGINT; s: ARRAY OF CHAR);
 VAR
  a: NodePtr;
 BEGIN
  a:=list;
  Allocate(list, SIZE(Node));
  list^.next:=a;
  list^.id:=id;
  CopyString(s, list^.data)
 END AddNode;

BEGIN
 list:=NIL;
 AddNode(4, "Hello");
 AddNode(3, "the");
 AddNode(1, "Computer");
 AddNode(2, "World")
END test.mod
\end{verbatim}

Nachdem Sie das Programm "ubersetzt und gelinkt haben, starten sie es,
indem Sie "`{\tt test}"' eingeben. Unmittelbar nach dem Start erscheint ein
Requester mit der Fehlermeldung "`{\tt Bereichsfehler (CHK)}"'. Wenn Sie zuvor
den Hintergrundprozess {\tt m2debug} bereits gestartet haben, 
oder dies in diesem Moment nachholen, haben Sie nun
die M"oglichkeit, unseren Debugger zu aktivieren. Wir w"ahlen im
Requester die Option {\tt debug}, und auf einem neuen Screen erscheinen
die f"unf Fenster des Debuggers. Im Modulfenster sehen Sie die Liste
der benutzten Moduln:

\begin{verbatim}
0   Arts     00215AA8
1   test     002067A8
2   Heap     00215B54
3   ExecL    00215B5C
4   DosL     00215B64
\end{verbatim}

Der obige Ausschnitt zeigt, dass unser Programm {\tt test} als Modul 1
geladen ist. Im Fenster "`{\tt Aufrufkette}"' wird die Fehlerursache und die
Prozedur-Aufrufkette dargestellt:

\begin{verbatim}
-- Bereichsfehler (CHK)
CopyString    in test
AddNode       in test
test          in test
\end{verbatim}

Wie wir in diesem Fenster sehen, ist ein Bereichsfehler --- hervorgrufen
durch einen Prozessortrap der MC68000 Instruktion {\tt CHK} --- in der Prozedur
{\tt Copy\-String} aufgetreten. Diese Prozedur wurde von der Prozedur
{\tt Add\-Node} aufgerufen, die wiederum vom Hauptprogramm {\tt test}
aufgerufen wurde. Da der Debugger die Referenzdatei des Moduls {\tt test}
gefunden hat, kann er alle Prozedurnamen ausschreiben. Sonst h"atte
der Debugger nur die Anfangsadresse der Prozedur ausgeben k"onnen.

Im Quelltext-Fenster sehen wir, wo genau der Fehler passierte. Die
Zuweisung

\begin{quote}\tt 
out[i]:=in[i]
\end{quote}

wird vom Debugger invertiert dargestellt. Die fehlerhafte Anweisung ist
zun"achst vertikal eingemittet; Sie k"onnen jedoch den Quelltext beliebig
durchbl"attern. Der Zugriff auf das i-te Element
des Feldes {\tt in} oder {\tt out} hat den Fehler verursacht.

Im Prozedur-Fenster k"onnen wir durch Anklicken einer Zeile mit der
rechten Maustaste auch die Fehlerstelle in den anderen Prozeduren
betrachten. Klicken wir die Zeile mit der Prozedur {\tt Add\-Node} an, so
erscheint im Fenster "`{\tt Quelltext}"', wiederum hervorgehoben:

\begin{quote}\tt 
CopyString(s, list\^.data)
\end{quote}

Dies ist besonders n"utzlich, wenn eine Prozedur an mehreren Stellen
aufgerufen wird. So ist n"amlich die Umgebung der aufgerufenen Prozedur
ersichtlich.

Im Daten-Fenster 1 erscheinen die lokalen
Variablen der Prozedur {\tt Copy\-String}

\begin{verbatim}
-- CopyString
-- Type = PROCEDURE
in       *    (dyn)  ARRAY
out      *    (dyn)  ARRAY
i                 6  INTEGER
\end{verbatim}

Durch Anklicken der linken Maustaste auf {\tt in}, erscheint folgende Ausgabe:

\begin{verbatim}
-- CopyString.in
-- Type = ARRAY (ARRAY [0..7] OF CHAR)
0        "C"  CHAR
1        "o"  CHAR
2        "m"  CHAR
3        "p"  CHAR
4        "u"  CHAR
5        "t"  CHAR
6        "e"  CHAR
7        "r"  CHAR
\end{verbatim}

In der obersten Zeile finden wir den Namen der aktuellen Struktur. In
unserem Falle ist dies die Variable {\tt in} in der Prozedur {\tt CopyString}.
Sollen weitere Variablen in der Prozedur {\tt CopyString} angeschaut
werden, k"onnen wir in der obersten Zeile mit dem linken Mausknopf den
Bezeichner {\tt CopyString} anklicken. Dadurch kehren wir wieder in die
vorangehende Umgebung zur"uck. Nun lassen wir uns noch die Variable {\tt out}
anzeigen.

\begin{verbatim}
-- CopyString.out
-- Type = ARRAY (ARRAY [0..5] OF CHAR)
0        "C"  CHAR
1        "o"  CHAR
2        "m"  CHAR
3        "p"  CHAR
4        "u"  CHAR
5        "t"  CHAR
\end{verbatim}

Wir erkennen nun die Fehlerursache. Das Feld {\tt out} umfasst nur 6 Elemente
von 0 bis 5. Die Variable {\tt i} hat den Wert 6, wie in der urspr"unglichen
Anzeige unschwer zu erkennen war. Somit f"uhrte die Zuweisung zum 7.
Element zum Bereichsfehler.

Als weiteres Beispiel f"ur das leistungsf"ahige Bl"attern in den
Datenstrukturen folgen die m"oglichen Ausgaben, wenn die globale
Zeigerkette {\tt list} n"aher betrachtet werden soll. Von Anfang an sind
im Daten-Fenster 2 alle modulglobalen Daten angezeigt: In diesem Fall
ist dies nur die Variable {\tt list}

\begin{verbatim}
-- test
-- Type = MODULE
list     * 00206440  NodePtr
\end{verbatim}

Durch Anklicken des Bezeichners {\tt list} wird der Inhalt angezeigt.
Dieser besteht aus einem weiteren {\tt NodePtr}, einem {\tt LONGINT} und einer
Zeichenkette.

\begin{verbatim}
-- test.list^
-- Type = Node (RECORD)
next     * 002063C8  NodePtr
id                1  LONGINT
data     *        6  String
\end{verbatim}

Anklicken des Elementes {\tt next} erm"oglicht das weitere Entlangwandern
der Zeigerliste. Dort sind logischerweise die gleichen Elemente
vorhanden, diese sind jedoch mit anderen Werten gef"ullt

\begin{verbatim}
-- test.list^.next^
-- Type = Node (RECORD)
next     * 002063B0  NodePtr
id                3  LONGINT
data     *        6  String
\end{verbatim}

Wird das {\tt data} Feld angeklickt, l"asst sich der aktuelle Inhalt der
Zeichenkette anschauen. Dabei ist der Inhalt der Elemente 4 und 5 nicht
von Belang, da das Element 3 ein Nullzeichen (0C = {\tt ASCII.nul})
enth"alt, womit die Zeichenkette logisch beendet ist.

\begin{verbatim}
-- test.list^.next^.data
-- Type = String (ARRAY [0..5] OF CHAR)
0    "t"  CHAR
1    "h"  CHAR
2    "e"  CHAR
3     0C  CHAR
4   233C  CHAR
5    "Z"  CHAR
\end{verbatim}
