 
\chapter{Bibliotheksmoduln}

\label{biblio}
\thispagestyle{empty}

\section{AMScan}

Die Prozedur {\tt ScanString} liest eine Zeichenkette ein und speichert
diese in {\tt str}. F"uhrende Leerzeichen werden "ubersprungen. Die
Leseprozedur muss dazu "ubergeben werden. Der Lesevorgang der
Zeichenkette wird durch ein Leerzeichen, einen Tabulator ({\tt ASCII.ht})
oder einen Strichpunkt ("`{\tt ;}"') beendet.
Soll eines dieser drei Zeichen in
die Zeichenkette eingef"ugt werden, muss dieses in Anf"uhrungszeichen
({\tt "'}) gesetzt werden. Das letztgelesene Zeichen wird
in {\tt termCh} gespeichert,
die L"ange der Zeichenkette in {\tt len}.
Das Resultat dieser Prozedur ist {\tt TRUE},
falls mindestens ein Zeichen eingelesen wurde.

\begin{example}
Beispiele:
{\tt Dieser Text }\ldots
"`{\tt Dieser}"' wird zur"uckgegeben.
{\tt Dies"'mal ist's"' besser}
"`{\tt Diesmal ist's}"' wird zur"uckgegeben.
\end{example}

\begin{note}
AMScan ist eine Variante des Moduls Scan (\ref{Scan}),
die urspr"unglich nur intern
(z.B.\ im Compiler) verwendet wurde.
\end{note}

\newpage

\section{Arguments}

Das Modul {\tt Arguments} erlaubt den Zugriff auf
die Programmargumente, die der Benutzer beim Aufstarten
des Programms angibt. Unterst"utzt werden Argumente,
die vom CLI aus auf der Befehlszeile oder auf der
Workbench durch erweiterte Selektion "ubergeben werden.

Die Prozedur {\tt NumArgs} liefert die Anzahl der
Programmargumente. Diese Zahl gibt entweder die
Anzahl Argumente der Befehlszeile oder die
Anzahl selektierter Workbench-Ikonen an. Wurde
das Programm ohne Argumente aufgerufen. liefert
{\tt NumArgs} den Wert 0.

Die Funktion {\tt GetArg} liefert den Wert des gew"unschten
Arguments, sofern dieses existiert. Ein Aufruf mit Argumentnummer
{\tt arg=0} liefert den Namen des aufgestarteten Programms.
Ebenfalls wird die Anzahl der Zeichen durch den Parameter
{\tt len} zur"uckgegeben.
Bei jedem Aufruf von {\tt GetArg} erh"alt die Variable
{\tt quoted} den Wahrheitswert {\tt TRUE}, falls das
Argument doppelte Anf"uhrungszeichen enthielt. Dies
erm"oglicht die Unterscheidung von Schl"usselw"ortern
und Argumenten des gleichen Namens.

\begin{example}
So zeigt
\begin{quote} \tt dir \dq all\dq \end{quote}
den Inhalt des Verzeichnisses "`{\tt all}"', w"ahrend
\begin{quote} \tt dir all \end{quote}
den gesamten Verzeichnisbaum des aktuellen Verzeichnisses
ausgibt.
\end{example}

{\tt GetArg} verbirgt die Unterschiede der Parameter"ubergabe
von CLI und Workbench vor dem Benutzer. W"ahrend ein
Argument der Befehlszeile aus einer einfachen Zeichenkette
besteht, setzt sich ein Workbench-Argument aus zwei Bestandteilen
zusammen. Einerseits ist das der Name des Arguments und
andererseits eine Referenz auf das Verzeichnis der entsprechenden
Datei. Bei Workbench-Argumenten setzt der Aufruf von {\tt GetArg}
das aktuelle Verzeichnis des Programms auf das Verzeichnis der
Argumentdatei. Dies geschieht durch einen Aufruf der Funktion
{\tt Dos.CurrentDir}.

Die Befehlszeile wird folgendermassen interpretiert: Leerschl"age
werden als Trennung zwischen zwei Argumenten ausgelegt. Durch
die Verwendung von doppelten Anf"uhrungszeichen k"onnen
aber auch Leerschl"age in das Argument eingef"ugt werden.
Alle Zeichen innerhalb zweier Anf"uhrungszeichen werden
unver"andert in das Argument "ubernommen. Die
Anf"uhrungszeichen selbst "uben keine Trennfunktion aus.

Ab AmigaDOS Version 1.3 bezeichnet ein leeres Argument
das aktuelle Verzeichnis, beispielsweise
beim {\tt copy}-Befehl. Daher ist es {\em unzul"assig},
mit der Verarbeitung der Argumente aufzuh"oren, wenn
die Argumentl"ange Null ist. Zun"achst muss die
Funktion {\tt NumArgs} aufgerufen und mit
diesem Wert gearbeitet werden.

Die Funktion {\tt GetLock} gibt dann einen g"ultigen
{\tt FileLockPtr} zur"uck, wenn das Programm von der
Workbench aufgerufen wurde. Dieser verweist
auf das Verzeichnis des zugeh"origen Arguments.%
\footnote{Bei fr"uheren Versionen musste dieser
Lock durch {\tt Dos.UnLock} explizit wieder freigegeben werden.
Dies ist {\em nicht mehr\/} der Fall.}


Wird das Programm vom CLI aus aufgerufen, bleibt ein
Aufruf von {\tt GetLock} ohne Wirkung. Als Resultat wird
{\tt NIL} zur"uckgegeben.

\newpage

\section{Arts}

Die Schnittstelle zu {\tt Arts}\footnote{Arts ist ein
Akronym gebildet aus "`Amiga Runtime System"', auf Deutsch
schlicht "`Amiga Laufzeitsystem"'} erlaubt den Zugriff auf einige
Funktionen des \mtwoamiga\ Laufzeitsystems.

\begin{warning}
Verwenden Sie diese Prozeduren und Variablen nur, wenn Sie genau
wissen, welchem Zweck sie dienen! Jede Fehlmanipulation kann zu
unvorhersehbaren Resultaten f"uhren.
\end{warning}

Das Modul {\tt Arts} hat das Erscheinungsbild eines
normalen Bibliotheksmoduls, bestehend aus einer Symbol-
und einer Objektdatei. Die Aufgaben von {\tt Arts} sind
jedoch weitaus vielf"altiger und spezieller. {\tt Arts}
ist das sogenannte {\bf Laufzeitsystem}, das die Basis
jedes Modula-2 Programms bildet. Es wird von jedem Modul
implizit importiert; die Symboldatei muss daher f"ur
jedem Compilationsvorgang zugreifbar sein.

Die Variable {\tt oldCurrentDir} enth"alt das aktuelle Verzeichnis des Prozesses
beim Programmstart (\verb|thisTask^.currentDir|). Bei Beendigung des Programmes
wird dieser Wert wieder als aktuelles Verzeichnis angemeldet. Falls
ein Programm das aktuelle Verzeichnis permanent wechseln m"ochte,
wie beispielsweise das CLI-Kommando "`CD"', muss das neue Verzeichnis in dieser
Variablen vermerkt werden. Beim Start von der Workbench steht hier
immer der Wert {\tt NIL} --- was man auch nicht "andern darf ---,
die Prozedur
{\tt Startup} wechselt in diesem Fall jedoch in das Verzeichnis,
in dem sich das Programm befindet.

F"ur den Anwender sind nur die letzten sechs Prozeduren allgemein
verwendbar.

Die Prozedur {\tt Assert} "uberpr"uft, ob eine Bedingung erf"ullt ist,
die f"ur den
korrekten Weiterlauf des Programmes unbedingt erforderlich ist. Ist
diese Bedingung nicht erf"ullt, erscheint ein Requester mit der
angegebenen Meldung, und nach Beantwortung durch den Anwender
wird das Programm abgebrochen.

{\tt BreakPoint} erzeugt einen Requester und l"asst dem Anwender
die Wahl zwischen dem Abbruch oder der
Fortf"uhrung des Programms. In erster Linie findet sie
ihre Anwendung im Zusammenhang mit dem Post-Mortem-Debugger, wo sich
dessen Aufrufm"oglichkeit erzwingen l"asst.

{\tt Error} zeigt in einem Requester die beiden Texte {\tt header}
 und {\tt body}
an und erzwingt einen Programm-Abbruch. Enth"alt der Parameter
{\tt body} den Wert {\tt NIL},
wird nur eine Zeile Text angezeigt.

Die Darstellung eines Requesters kann mittels der
Prozedur {Requester} mit den angegebenen Texten
{\tt header} und {\tt body} erreicht werden.
Die Felder {\tt pos} und {\tt neg} zeigen auf die Texte, die
in die Gadgets geschrieben werden. Der Parameter {\tt pos} kann auch
{\tt NIL} sein; dann
enth"alt der Requester nur ein Gadget. Der R"uckgabewert von
{\tt Requester} gibt an, welches Gadget gew"ahlt wurde. Wurde das Gadget
mit dem Text von {\tt pos} ausgew"ahlt, ist der Resultatswert {\tt TRUE},
anderenfalls {\tt FALSE}.

Die Prozedur {\tt Terminate} beendet einfach das Programm.
Der in diesem Moment
in der Variablen {\tt returnVal} enthaltene Wert dient als R"uckgabewert
an das Betriebssystem. "Ahnlich arbeitet 
{\tt Exit}. Hier kann allerdings der R"uckgabewert
explizit angegeben werden.


\newpage

\section{ASCII}

Das Modul ASCII definiert Namen f"ur die
ASCII\footnote{American Standard Code for Information
Interchange}-Steuerzeichen.

\begin{note}
Auf dem Amiga hat das Steuerzeichen "'line feed"' ({\tt lf}) die Funktion
des Zeilenendes ({\tt eol}).
\end{note}

\begin{note}
Das Zeichen "'command sequence introducer"' ({\tt csi}) ist
kein ASCII-Kontrollzeichen, sondern ein spezielles
Bildschirmsteuerungs-Zeichen, das oft in Kontroll-Sequenzen
wie f"ur die Ausgabe auf das {\tt RAW:}-Device ben"otigt
wird.
\end{note}

\begin{note}
Es existiert {\em keine\/} Objektdatei zum Modul ASCII.
\end{note}

\newpage

\section{Break}

Mit Hilfe des Moduls {\tt Break} kann ein Programm sehr flexibel auf
die durch das DOS generierten Signale bei \keyctrl[C], \keyctrl[D],
\keyctrl[E] und \keyctrl[F] reagieren.

Mit Hilfe der Prozedur {\tt SetBreakMode} kann festgelegt werden, auf welche
dieser vier Signale "uberhaupt geachtet werden soll. Bei Programmstart
ist dies nur \keyctrl[C].

Die Prozedur {\tt ExitBreak} schreibt den Text "`{\tt *** BREAK}"'
auf den Bildschirm
und beendet das Programm.

{\tt TestBreak} "uberpr"uft, ob eines der erlaubten Signale eingetroffen
ist und beendet in diesem Fall "uber {\tt ExitBreak} das Programm.

Durch {\tt GetBreak} kann man sich die bis dahin eingetroffenen Signale
ansehen und je nach Fall entsprechend reagieren; z.B. bei \keyctrl[C]
mit Programmabbruch, bei \keyctrl[D] mit Beendigung der aktuellen Datei,
bei \keyctrl[E] mit Beendigung des aktuellen Arbeitsganges usw.

Der einfache Aufruf von {\tt InstallException} bewirkt, dass man sich
um eine Abfrage nicht mehr selbst k"ummern muss. Das Programm wird
durch \keyctrl[C] --- unter Umst"anden mehrfach n"otig --- asynchron mit der
BREAK-Meldung beendet. {\tt RemoveException} stellt den Normalzustand
wieder her. Das diese Prozedur nur auf \keyctrl[C] wirkt, ist eine
Mischung beider Methoden durchaus m"oglich.

\begin{warning}
Ein asynchroner Programm-Abbruch kann zum Sy\-stem-Ab\-sturz f"uhren, wenn
das Programm zur Zeit auf ausstehende
Meldungen\footnote{Message-Mechanismus von {\tt ExecL}} wartet.
Man sollte in
diesem Fall kurzzeitig durch {\tt RemoveException} die M"oglichkeit
ausschalten! Der durch
{\tt InstallException} installierte Handler kann nur das Warten auf Dos-Signale
"uberpr"ufen und in diesem Fall den Wunsch des Benutzers nach Abbruch
ignorieren.
\end{warning}
Die einfachste Methode ist also der IMPORT von Break und dann
ein Aufruf von {\tt InstallException}, die sicherere Methode besteht
darin, beispielsweise innerhalb einer Schleife,
insbesondere bei Ausgaben auf den Bildschirm, 
{\tt TestBreak} aufzurufen.

\newpage

\section{Call}

Das Modul {\tt Call} dient dazu, von jedem Ort, aus jeder Prozedur
an einen bestimmten Ort zur"uckkehren zu k"onnen. Falls ein Modul
aus einer Hauptschleife besteht, in die immer wieder zur"uckgekehrt
werden soll, so ruft man in dieser Hauptschleife die eigentliche
Prozedur mittels {\tt Call(Proc)} auf. {\tt Proc} kann nun beliebig tief
verschachtelte andere Prozeduren (normal) aufrufen. Im Ausnahmefall
sollte das Programm hier nicht durch die Prozedur {\tt Arts.Terminate}
abgebrochen,
oder ein Fehlerparameter durch s"amtliche Prozeduren zur"uckgereicht
werden. Stattdessen reicht ein einfaches {\tt Return}, und man befindet
sich wieder in der Hauptschleife. Dies ist zwar eine "`unsaubere"'
Art der Programmierung, aber dann angebracht, wenn beispielsweise
jederzeit auf asynchrone Ereignisse reagiert werden muss.

Dieser Mechanismus kann bis zu acht Levels verwalten. Ein weiteres
{\tt Call} f"uhrt zu einem Laufzeitfehler. Ein {\tt Return}
ohne vorheriges {\tt Call()} beendet einfach das Programm.

\newpage

\section{CommoditiesSupport}

Dies Modul ist eine Hilfestellung f"ur Schreiber von Commodities.
Es enth"alt alle Prozeduren,
die in den Autodocs \verb|cx_lib.doc|\index{cx_lib.doc}
beschrieben sind. Unter \mtwoamiga\ ist zu beachten,
dass {\tt ArgArrayInit}
und {\tt ArgArrayDone} nicht aufgerufen werden; dies erledigt das Modul
selbst"andig.

\newpage

\section{Conversions}

Das Modul {\tt Conversions} stellt die beiden wichtigsten
Prozeduren zur Umwandlung von ganzen Zahlen aus der lesbaren
in die interne Darstellung und umgekehrt zur
Verf"ugung. Dabei ist es m"oglich, sowohl vorzeichenbehaftete
sowie vorzeichenlose Gr"ossen umzuwandeln.

Die Prozedur {\tt StrToVal} wandelt von der lesbaren zur internen
Darstellung um. Die Zeichenkette {\tt str} enth"alt eine Zahl
zur Basis {\tt base}. Diese Zahlenbasis kann jeden Wert zwischen
2 und 16 annehmen, die verwendeten Zeichen m"ussen allerdings
innerhalb des entsprechend g"ultigen Bereichs {\tt [0..base-1]}
sein. Zahlen in Oktaldarstellung erlauben so Zeichen zwischen
{\tt '0'} und {\tt '7'}, solche in Hexadezimaldarstellung die
Zeichen {\tt '0'} bis {\tt '9'} und {\tt 'A'} bis {\tt 'F'}.
Die Zeichenkette darf insbesondere auch keine Leerzeichen
enthalten, das Nullzeichen ({\tt 0C}) als Abschlusszeichen
ist selbstverst"andlich erlaubt. Das Resultat wird im
{\tt LONGINT}-Parameter {\tt l} abgelegt. Ein Fehler ---
angezeigt durch den Parameter {\tt err} --- kann durch
folgende Ereignisse verursacht sein:
\begin{itemize}
\item
  Die Zahlenbasis ist ausserhalb des erlaubten Bereichs
  von 2 und 16.
\item
  Die Eingabe-Zeichenkette enth"alt Zeichen, die nicht zur
  angegebenen Basis passen.
\item
  Der resultierende Wert kann nicht in einem {\tt LONGINT}
  gespeichert werden.
\end{itemize}

Ist der Resultatswert {\tt l} negativ und hat {\tt signed}
gleichzeitig den Wert {\tt FALSE}, so wurde eine Zahl
"ubergeben, die kein Minuszeichen enth"alt, deren Wert aber
nicht in einer {\tt LONGINT}-Zahl abgespeichert werden kann.
In diesem Fall ist die Zahl {\tt l} in einem {\tt LONGCARD}
abzuspeichern. Entweder wird ein Varianten-Verbund
("'{\tt CASE-RECORD}"') "ubergeben, oder man muss sich mit einer
{\tt CAST}-Anweisung des Moduls {\tt SYSTEM} behelfen.

Die umgekehrte Umwandlung wird durch die Prozedur {\tt ValToStr}
durchgef"uhrt. Die im {\tt LONGINT}-Parameter {\tt l} abgelegte
Zahl wird in die Zeichenkette {\tt str} umgewandelt und formatiert.
Die Zahl wird in einem Feld der Gr"osse {\tt width} (Absolutbetrag)
positioniert. Das Vorzeichen von {\tt width} bestimmt die Anordnung
der Zahl im Feld. Bei einem positiven Wert von {\tt width} wird
die Zahl im Feld rechtsb"undig, mit f"uhrenden F"ullzeichen
{\tt fillChar}, sonst linksb"undig mit nachfolgenden F"ullzeichen,
angeordnet.

F"ur das Vorzeichen von {\tt l} und dem Wert von {\tt signed}
gilt die gleiche Konvention wie bei {\tt StrToVal}. Zahlen und
Zeichenketten, die ausschliesslich mit {\tt Conversions} bearbeitet
werden, ben"otigen daher keine weitere Bearbeitung.

\begin{example}
\begin{alltt}
str:="03F9";
large:="3000000000"; \hfill (* $>2^{31}$ *)
StrToVal(str,number,signed,16,err);
  (* number: 1017
     signed: FALSE
     err:    FALSE *)
StrToVal(str,number,signed,10,err);
  (* number: {\rm undefiniert}
     signed: {\rm undefiniert}
     err:    TRUE {\rm Zeichenkette f"ur Basis 10 ung"ultig} *)
StrToVal(large,number,signed,16,err);
  (* number: -1294967296
     signed: FALSE (* {\rm Ursprungszahl war positiv} *)
     err:    FALSE *)

ValToStr(27,FALSE,str,8,5,'*',err);
  (* str: "`***33"'
     err: FALSE *)
ValToStr(45054,FALSE,str,16,-10,' ',err);
  (* str: "`AFFE      "'
     err: FALSE *)
\end{alltt}
\end{example}

\begin{note}
Die interne Darstellung (Zweierkomplement) der
Zahl {\tt 3'000'000'000} ({\tt LONGCARD}) ist gleich
der internen Darstellung der Zahl {\tt -1'294'967'296}
({\tt LONGINT}).
\end{note}

\newpage

\section{Coroutines}

Dieses Modul erlaubt die Handhabung von {\bf Coroutinen}. Coroutinen
unterscheiden sich dadurch von Prozeduren, dass sie nicht
bei jedem Aufruf vom Startpunkt aus durchlaufen werden. Stattdessen
kann eine Coroutine jederzeit (explizit) unterbrochen werden,
und beim erneuten Eintritt in die Coroutine wird die der
Unterbrechungs-Anweisung unmittelbar folgende Anweisung als
n"achste ausgef"uhrt.

Coroutinen sind die Basis von quasi-parallel ablaufenden Prozessen.
Im Gegensatz zu diesen ist f"ur Coroutinen {\em keine\/}
Unterst"utzung des Betriebssystems n"otig. Echte Prozesse
sind nur mit den Routinen der Schnittstellen-Moduln {\tt ExecL}
oder {\tt DosL} m"oglich.

Prozedur {\tt NEWPROCESS} ruft eine neue Coroutine ins Leben,
wobei die Prozedur {\tt p} die neue Coroutine bildet.
Die Variablen {\tt wsp} und {\tt size} bezeichnen den zur Verf"ugung
gestellten Arbeitsspeicher, erstere gibt die Adresse, letztere
die Gr"osse des Arbeitsspeichers. Die Variable {\tt new}
charakterisiert die neu kreierte Coroutine. Die Coroutine
wird {\em nicht\/} gestartet, sondern nur initialisiert.
Danach kann jederzeit durch {\tt TRANSFER} in die Coroutine
gesprungen werden.

Der Arbeitsspeicher muss alle lokalen Variablen der
Coroutine und der von ihr aufgerufenen Prozeduren
beinhalten. Es k"onnen daher keine allgemeing"ultigen
Werte f"ur die optimale Gr"osse des Arbeitsspeichers
angegeben werden.

Da innerhalb einer Coroutine Dos-Aufrufe m"oglich sind, muss
sichergestellt werden, dass gen"ugend Arbeitsspeicher angelegt wird. F"ur
Dos-Aufrufe werden bis zu 1500 Byte ben"otigt. Falls keine
Dos-Aufrufe in der Coroutine sind, k"onnen Sie diese Variablen auf
kleinere Werte setzen. Die Variable {\tt coroutinesMinStack}
ist die minimale Gr"osse
des Arbeitsspeichers, die bei {\tt NEWPROCESS} erwartet wird.
{\tt coroutinesSaveStack} reserviert einen Bereich dieser Gr"osse im
Arbeitsspeicher f"ur nicht kontrollierbare Aufrufe (z.B. Dos). Sobald
mehr als {\tt size} - {\tt coroutinesSaveStack} Byte des Arbeitsspeichers
in Gebrauch sind, wird das Programm mit einem Stapel"uberlauf abgebrochen.

{\tt TRANSFER} suspendiert die durch {\tt source} charakterisierte 
Coroutine, w"ah"-rend mit {\tt dest} an der Stelle der Suspension
fortgefahren wird. Wird {\tt source} wieder fortgesetzt, wird die
unmittelbar auf {\tt TRANSFER} folgende Anweisung ausgef"uhrt.

\newpage

\section{DateConversions}

Das Modul {\tt DateConversions}
enth"alt Prozeduren, die das Konvertieren von Zeit-
und Datumswerten in verschiedenen Darstellungen erlaubt. Diese Prozeduren
funktionieren nur, wenn sich das Datum zwischen dem 1. M"arz 1900 und dem
28. Februar 2099 befindet.

Im Modul ist ein eigener Typ {\tt DateInfo} definiert,
in dem Datum und Uhrzeit
in Form von Anzahl Minuten und Mikrosekunden seit dem 1. M"arz 1900
abgelegt sind.

Die Prozeduren {\tt FromDos} und {\tt ToDos}
erlauben es, Datum und Zeit im vom 
Dos gelieferten Format ({\tt DosD.Date}) zu und von dem Format von
{\tt DateInfo} zu wandeln.

Die Prozeduren {\tt FromTimer} und {\tt ToTimer} erlauben es,
die Zeit im Format, wie
sie vom {\tt timer.device} geliefert werden
({\tt Timer.TimeVal}), zu und von demjenigen von 
{\tt DateInfo} zu wandeln.

Die Prozeduren {\tt DecodeDate} und {\tt EncodeDate} konvertieren ein Datum
ohne Uhrzeit in eine Minutenwert, der in einer Variablen vom
Typ {\tt DateInfo} abgelegt werden kann.

{\tt DateToStr} schliesslich erlaubt die Wandlung von Datum und Zeit in eine
Zeichenkette. {\tt DateToStr} bietet eine sehr
flexible Formatierungsm"oglichkeit.
{\tt formatString} gibt dabei an, wie die in {\tt output}
erstellte Zeichenkette
auszusehen hat. Alle Buchstabenpaare der Formatzeichenkette, die mit einem
{\tt \%}-Zeichen beginnen, werden auf spezielle Art behandelt. Alle anderen
Buchstaben werden unver"andert in {\tt output} "ubernommen. Die speziellen
Buchstabenpaare sind:

\begin{ttscript}{xx}
\item[\%E] Escape Zeichen ({\tt ASCII.esc}).
\item[\%N] Neue Zeile ({\tt ASCII.eol}).
\item[\%T] Tabulator ({\tt ASCII.ht}).
\item[\%\%] wird als ein einzelnes Prozentzeichen weitergegeben.
\item[\%d] Tag als zweistellige Ziffer mit f"uhrender 0.
\item[\%m] Monat als zweistellige Zahl mit f"uhrender 0.
\item[\%t] Monat als Text. Die Monatsnamen werden
  dem Parameter {\tt monthText} entnommen.
  {\tt monthtext} muss dazu zw"olf Worte enthalten,
  die durch ein "`{\verb/|/}"' voneinander
  getrennt sind und die Namen der Monate Januar bis Dezember enthalten.
  Zwei m"ogliche Zeichenketten f"ur {\tt monthText} sind
  in den Konstanten {\tt month}
  und {\tt month3} enthalten.
\item[\%y] Einer- und Zehnerstelle des Jahrs als
  zweistellige Zahl mit f"uhrender 0.
\item[\%Y] Jahr als vierstellige Zahl.
\item[\%H] Stunde als zweistellige Zahl mit f"uhrender 0.
\item[\%M] Minute als zweistellige Zahl mit f"uhrender 0.
\item[\%S] Sekunde als zweistellige Zahl mit f"uhrender 0.
\item[\%1] Zehntelsekunde als einstellige Zahl mit f"uhrender 0.
\item[\%2] Hundertstelsekunde als zweistellige Zahl mit f"uhrender 0.
\item[\%3] Tausendstelsekunde als dreistellige Zahl mit f"uhrender 0.
\item[{\rm \ldots}]
\item[\%6] Millionstelsekunde als sechsstellige Zahl mit f"uhrender 0.
\end{ttscript}

\begin{example}
Beispiele: Das Beispiel nimmt an,
dass die aktuelle Zeit 22 Uhr 33 Minuten
21.423178 Sekunden und das Datum der 25. Juli 1989 ist.

\begin{verbatim}
 DateToStr(di,"Date: %d. %t %Y  Time: %H:%M:%S.%3%N",
   month,str);
 WriteString(str);
 DateToStr(di,"%Y%m%d%H%M/cn%N","",str);
 WriteString(str)
 DateToStr(
  di,"Der Name dieses Monats beginnt mit einem %t.%N",
  "J|F|M|A|M|J|J|A|S|O|N|D",str
 );
 WriteString(str)
\end{verbatim}

Die Ausgabe dieser Programmzeilen ist:

\begin{verbatim}
 Date: 25 July 1989  Time: 22:33:21.423
 198907252233/cn
 Der Name dieses Monats beginnt mit einem J.
\end{verbatim}
\end{example}

\newpage

\section{Detach}

Mit Hilfe des Moduls {\tt Detach} kann das aktuelle Programm
einfach von der Shell abgekoppelt werden. Dieses Modul arbeitet
allerdings nur unter Kickstart Version 2.0.

Das Modul {\tt Detach} ersetzt im Grunde einen Aufruf mittels
\begin{quote}
\verb|"run >outfile <infile prog"|
\end{quote}
wobei {\tt infile} und {\tt outfile} meist
durch {\tt NIL:} ersetzt werden.
Diese Methode des Aufrufs hat jedoch den Nachteil, dass ein Programm
{\em sofort\/} abgekoppelt ist. Oftmals sollen jedoch beim Starten anfallende
Fehler- oder sonstige Meldungen noch ausgegeben werden. Man denke
auch an den Syntax-Aufruf "`{\tt prog ?}"'.

Genau dies erm"oglicht {\tt Detach}.
Der Aufruf der Abkoppelungs-Prozedur
erfolgt erst bei Bedarf und wenn "`alles klar"' ist.
F"ur den Einsatz m"ussen folgende Voraussetzungen
erf"ullt sein:
\begin{itemize}
\item die Kickstart-Version muss mindestens 37 betragen;
  dies wird abgefangen.
\item das Programm muss reentrant sein, dies wird allerdings
  {\em nicht\/} abgefangen!
\end{itemize}

Die Prozedur {\tt Detach}
erzeugt einen neuen Prozess mit den angegebenen Parametern.
Dabei ist {\tt name} der Kommandoname, nicht der Name des
Prozesses. Der Prozessname ist immer "`{\tt Detached Process}"'.
{\tt pri} ist die Priorit"at im Bereich von -128 bis 127.
Der Parameter {\tt stackSize} ist die Gr"osse
des Stacks in Byte, residentf"ahige
Programme nehmen sich jedoch immer die beim Linken angegebene
Stackgr"osse! Die beiden FileHandles
{\tt input} und {\tt output} m"ussen {\em neu\/} ge"offnet sein, also
keinesfalls Kopien von anderen Files. Sie werden automatisch
vom System geschlossen. Sind beide identisch,
wird nur einer geschlossen.

Zu beachten ist, dass beim Start von der Workbench das f"ur
Detach angegebene Fenster nicht ge"offnet wird, sondern das
"uber die Tooltypes angegebene, falls Terminal importiert wurde.


PROCEDURE DetachNorm(inname,outname:ARRAY OF CHAR);

Die Prozedur {\tt DetachNorm}
ist die einfachere Version von {\tt Detach}
und entspricht dem Aufruf
\begin{quote}\tt
Detach(programName, ownPri, ownStackSize, in, out)
\end{quote}
Ist {\tt outname} eine leere Zeichenkette, wird der FileHandle
des Parameters {\tt inname} "ubernommen.

\begin{example}
Der Aufruf sieht typischerweise so aus:

\begin{verbatim}
  IF AllesKlarZumAbheben THEN
    DetachNorm("con:0/20/400/100/Test/CLOSE/AUTO", "");
    Hauptprozedur();
  END;
\end{verbatim}
\end{example}

{\tt Detach} kehrt nur zur"uck, wenn das Programm von der Workbench oder
als Hintergrundprozess gestartet wurde.
Andernfalls, also durch normalen Shell-Start, wird das eigene
Programm als Hintergrundprozess gestartet und der Urprozess durch
{\tt Arts.Terminate} beendet.
Der neue Hintergrundprozess stellt nun bei seinem Aufruf von {\tt Detach}
fest, dass er kein Shell-Prozess ist und kehrt zur aufrufenden Prozedur
zur"uck, die nun die eigentliche Arbeit des Programms beginnen kann.

Dies h"ort sich simpel an, musste aber wegen mangelhafter Dokumentation
einiger Dos-Eigenschaften hart am Rande der Legalit"at programmiert
werden. Insbesondere die Tatsache, dass ein Programm auch resident
geladen werden kann machte das Modul relativ komplex.

Weil beide Prozesse einen Moment lang gleichzeitig auf der selben
Segmentliste laufen, operieren sie auf identischen Variablen, was
zum Absturz f"uhren w"urde. Dies kann bei residentf"ahigen Programmen
nicht passieren, da diese beim Start ihre eigenen Variablen anlegen.


\newpage

\section{DosSupport}

Beim Verwenden von Dos-Prozeduren, die einen {\tt Lock} oder {\tt FileHandle}
erzeugen, muss der Programmierer darauf achten, diese
am Programmende wieder freizugeben.

Dieses Modul enth"alt alle Dos-Prozeduren, die einen neuen
{\tt Lock} oder einen neuen {\tt FileHandle} erzeugen. Die Namen und Parameter
sind vom Modul {\tt DosL} "ubernommen. Diese hier
vermerkten Prozeduren merken sich alle allozierten Objekte,
um diese bei Programmende automatisch zu deallozieren.

\begin{warning}
{\tt FileHandle}s und {\tt Lock}s, die mit Prozeduren dieses Moduls erzeugt
 werden, d"urfen  auch nur mit diesen wieder
 freigegeben werden.

Solche, die mit Prozeduren des Moduls {\tt DosL}
 erzeugt wurden, d"urfen nur mit Prozeduren von {\tt DosL} wieder
 freigegeben werden.

 Bei Nichtbeachtung dieser Regeln muss mit einem unerwarteten
 Besuch des Gurus gerechnet werden.
\end{warning}

Wenn man sich entschieden hat, die Prozeduren dieses Moduls zu
verwenden, sollte man die gleichnamigen Prozeduren von {\tt DosL}
gleich ganz aus dem Programm verbannen.


Zu beachten ist, dass die Prozeduren {\tt DupLockFromFH},
{\tt OpenFromLock} und {\tt ParentOfFH} erst ab der
Library-Version 36 zur Verf"ugung stehen. Diese Prozeduren
brechen das Programm ab, wenn versucht wird, sie mit einer
Dos-Library geringerer Version aufzurufen.

\newpage

\section{ExecSupport}

Dieses Modul definiert einige Prozeduren, welche das Arbeiten mit
den Listen, Tasks, Ports und I/O-Operationen von {\tt Exec}
erleichtern.

{\tt NewList} initialisiert einen Listenkopf. Der Speicher f"ur
den Listenkopf muss schon zuvor alloziert werden. {\tt NewList}
beschr"ankt sich darauf, die einzelnen Zeiger des Listenkopfes
richtig zu setzen.

{\tt BeginIO} ruft die gleichnamige Routine des angegebenen
Device auf.

{\tt AbortIO} ruft die gleichnamige Routine des angegebenen
Device auf.

{\tt CreatePort} alloziert Speicherplatz und ein Signal f"ur einen {\tt MsgPort}
und f"uhrt auch alle n"otigen Initialisierungen durch. Falls der
{\tt portName} nicht {\tt NIL} ist, wird der Port als "offentlicher Port
eingetragen. Wenn der Port nicht mehr ben"otigt wird, muss er mit
{\tt DeletePort} wieder freigegeben werden.

{\tt DeletePort} dealloziert den f"ur den {\tt MsgPort}
allozierten Speicher und das allozierte Signal.

{\tt CreateExtIO} alloziert Speicher f"ur einen erweiterten I/O-Request.
Wird der I/O-Request nicht mehr ben"otigt, muss sein
Speicherplatz mit einem Aufruf von
{\tt DeleteExtIO} wieder freigegeben werden.

{\tt DeleteExtIO} gibt den Speicherplatz eines erweiterten
I/O-Request wieder frei.

{\tt CreateStdIO} wie {\tt CreateExtIO} aber f"ur einen "`standard"'
I/O-Request.

{\tt DeleteStdIO} wie {\tt DeleteExtIO} aber f"ur einen "`standard"'
I/O-Request.

{\tt CreateTask} erstellt einen neuen Task und f"ugt ihn in die
Task Liste ein. Der Task-Node wird dabei so initialisiert, dass
beim Beenden des Tasks sowohl der f"ur den Task-Node wie auch der f"ur den
Stack allozierte Speicher
automatisch freigegeben wird.

{\tt DeleteTask} beendet einen Task.

\newpage

\section{FFPConversions}

Das Modul {\tt FFPConversions} stellt die Prozeduren zur
Umwandlung von Gleitpunktzahlen (Dezimalbr"uchen) zwischen interner
und lesbarer Darstellung und umgekehrt zur Verf"ugung.
Dabei wird das spezielle FFP-Format verwendet.

Die Prozedur {\tt StrToReal} wandelt die in {\tt str}
gespeicherte Gleitpunktzahl in die interne FFP-Darstellung um.
Enth"alt die Zeichenkette nicht erlaubte Zeichen, oder kann
die beschriebene Zahl nicht in einer FFP-Variablen dargestellt
werden, erh"alt {\tt err} den Wert {\tt TRUE}.

Die Prozedur {\tt RealToStr} erlaubt vielseitige Umwandlungen
von {\tt r} in lesbare Darstellungsformen. Die resultierende
Zeichenkette enth"alt genau {\tt m} Zeichen, oder soviele
wie {\tt s} Platz bietet, falls {\tt m} zu gross ist.
Ist {\tt m} positiv, werden notwendige Leerzeichen
vor der Zahl angeh"angt, sonst werden sie angeh"angt. Die Anzahl
Zeichen hinter dem Dezimalpunkt wird durch {\tt n} gegeben. 
Falls in Ber"ucksichtigung zur Feldgr"osse
die Anzahl der Dezimalstellen zu gross gew"ahlt wurde, wird diese
auf das entsprechende Maximum gek"urzt. Ist {\tt n=0} wird
kein Dezimalpunkt geschrieben. Der Parameter {\tt expo} gibt an, ob die
wissenschaftliche Schreibweise (Exponentialdarstellung)
gew"unscht ist.

\begin{example}
\begin{alltt}
r:=12.976;
RealToStr(r,str,5,2,FALSE,err);
  (* str: "`12.98"'
     err: FALSE *)
RealToStr(r,str,4,2,FALSE,err);
  (* str: "`13.0"'
     err: FALSE *)
RealToStr(r,str,3,2,FALSE,err);
  (* str: "` 13"'
     err: FALSE *)
RealToStr(r,str,2,2,FALSE,err);
  (* str: "`13"'
     err: FALSE *)
RealToStr(r,str,1,2,FALSE,err);
  (* str: {\rm undefiniert}
     err: TRUE *)
RealToStr(r,str,-8,2,FALSE,err);
  (* str: "`12.98   "'
     err: FALSE *)
RealToStr(r,str,10,2,TRUE,err);
  (* str: "`  1.30E+01"'
     err: FALSE *)
\end{alltt}
\end{example}

M"ogliche Fehlerquellen --- durch den Parameter {\tt err}
mitgeteilt --- sind ein negativer Wert von {\tt n},
der Wert Null f"ur {\tt m} oder {\tt s} beinhaltet zu wenig
Zeichen, um die resultierende Zeichenkette abzuspeichern.

\newpage

\section{FFPInOut}

Dieses Modul entspricht dem Standardmodul {\tt RealInOut}
f"ur die Ein- und Ausgabe von Zahlen des Typs {\tt FFP}.
Der Ein- und Ausgabestrom wird vom Modul {\tt InOut}
(Seite \pageref{InOut}) kontrolliert.

Die Prozedur {\tt WriteReal} schreibt die "ubergebene Zahl
{\tt r} in ein Feld der Gr"osse {\tt m}, wobei im Maximum {\tt n}
Dezimalstellen geschrieben werden. F"ullt die Darstellung
das Feld nicht aus, wird dieses mit Leerzeichen ausgef"ullt.
Ist die Feldgr"osse positiv, werden die Leerzeichen vor der
Zahl gesetzt, sonst werden sie angeh"angt.

{\tt ReadReal} list eine Zeichenkette von der Eingabe
--- gegeben durch das Modul {\tt InOut} --- und wandelt
diese in die FFP-Zahl {\tt r} um.

\newpage

\section{FileMessage}

Das Modul {\tt FileMessage} liefert lesbare Fehlermeldungen
aus den Statuswerten des Moduls {\tt FileSystem}.

Die Prozedur {\tt ResponseText} gibt aus dem Dateistatus
{\tt res} den Zeiger {\tt p} zur"uck. Dieser
zeigt auf einen Text, der unmittelbar ausgegeben werden
kann.

\begin{example}
Aufruf:
\begin{alltt}
VAR
 f: File;
 p: StrPtr;
 {\rm\ldots}
 ResponseText(f.res, p);
 WriteString(p^); WriteLn;
 {\rm\ldots}
\end{alltt}
\end{example}

\begin{note}
{\tt ResponseText} weist dem Parameter {\tt p} die
Adresse der Zeichenkette im Konstantenbereich zu. Daher
darf diese Zeichenkette nicht ver"andert werden! Die Zeichenkette
darf auch nicht auf 256 Zeichen aufgef"ullt werden.
\end{note}

\newpage

\section{FileNames}

Modul f"ur die Behandlung von Dateinamen-Eingaben.

{\tt ReadFileName} liest einen Dateinamen mit den "ubergebenen Ein-
und Ausgabe-Prozeduren. {\tt len} gibt die Anzahl gelesenen Zeichen. Alle
Zeichen bis 176C werden akzeptiert.

\begin{example}\begin{verbatim}
ReadFileName(fname, len, Terminal.Read, noEcho);
Benutzereingabe: df1:exec/sym/Alerts.sym <RETURN>
fname="df1:exec/sym/Alerts.sym"; len=23;
\end{verbatim}\end{example}

{\tt GetPath} l"oscht die Pfadinformation aus {\tt fname}
und speichert diese in
{\tt path}. {\tt len} wird entsprechend dem neuen Dateinamen gesetzt.

{\tt GetExtension} arbeitet "ahnlich wie {\tt GetPath}, ausser dass die
Erweiterung gel"oscht wird. Als Erweiterung wird angenommen, was
hinter dem letzten Punkt steht.

{\tt MakeFileName} verkettet die 4 "ubergebenen Zeichenketten
aneinander und speichert den gesamten Dateinamen in {\tt fname}.

\newpage

\section{FileSystem}

Das Standardmodul {\tt FileSystem} bietet Prozeduren 
zur Dateibehandlung  an. Es erm"oglicht sowohl den sequentiellen
("'sequential access"') wie auch den wahlweisen
Zugriff ("'random access"') auf Dateien. Lese- und Schreiboperationen
k"onnen beliebig gemischt werden. Dateien, die Sie mit dem
Modul {\tt FileSystem} bearbeiten, werden beim Programmabsturz oder
-ende noch auf dem Dateisystem vervollst"andigt und
geschlossen.

Die Anzahl der gleichzeitig verwendbaren Dateien ist nur
durch das Betriebssystem beschr"ankt. Im Gegensatz zu AmigaDOS
ist der Dateizugriff durch das Modul {\tt FileSystem} gepuffert.
Dies kann den Zugriff bis zu Faktor 10 verschnellern. Die
Puffergr"osse muss beim Er"offnen der Datei festgelegt werden.

Eine Datei wird mit dem strukturierten Typ {\tt File} identifiziert.
F"ur den Anwender sind davon jedoch nur die Felder {\tt res} und
{\tt eof} von Bedeutung. Das Feld {\tt res} enth"alt das Resultat
der zuletzt ausgef"uhrten Dateimanipulation, w"ahrend {\tt eof}
das Dateiende anzeigt. Das Resultatsfeld sollte nach jedem 
Aufruf einer Prozedur aus {\tt FileSystem} kontrolliert werden,
die Pr"ufung auf das Dateiende muss nur nach Lesezugriffen erfolgen.
Die verbleibenden Felder verwalten den Puffer und stellen die
Verbindung zu AmigaDOS her.

Der Aufz"ahlungstyp {\tt Response} enth"alt die m"oglichen
Zust"ande, die nach einem Dateizugriff auftreten k"onnen.
Im Normalfall enth"alt das Feld {\tt res} den Wert {\tt done}.
Dies bedeutet, dass die letzte Operation erfolgreich ausgef"uhrt
wurde. Nebst der allgemeinen Fehlermeldung {\tt notDone}
enth"alt der Typ {\tt Response} einige AmigaDOS-spezifische
Meldungen.

Um die Behandlung von Fehlersituationen zu vereinfachen gilt folgende
Regel: Alle Prozeduren ausser {\tt Lookup} und {\tt Close} versuchen
die Operation nur auszuf"uhren, falls das Feld {\tt res} gleich
dem Wert {\tt done} ist. So ist es m"oglich, eine Datei vollst"andig
zu lesen oder zu schreiben, ohne jedes Mal auf einen Fehler
testen zu m"ussen. Die Prozeduren {\tt Lookup} und {\tt Close}
sind aus folgenden Gr"unden ausgenommen:

\begin{itemize}
\item
  {\tt Lookup} kann keine definierten Werte in der
  {\tt File}-Variablen erwarten, da erst der Aufruf
  dieser Prozedur die Variable mit g"ultigen Werten belegt.
\item
  {\tt Close} muss versuchen, eine Datei auch dann zu schliessen,
  wenn zuvor ein Fehler aufgetreten ist.
\end{itemize}

Es d"urfen keine Operationen ausser {\tt Lookup} auf
nichtinitialisierte Filevariablen ausgef"uhrt werden.

\begin{alltt}
\begin{example}
VAR
 f: file; ch: CHAR;
BEGIN
 Lookup(f, "'{\cmsltt Datei\/}"', 1024, FALSE);
 Assert(f.res=done, ADR("'Lookup misslungen!"');
 LOOP
  ReadChar(f, ch);
  IF f.eof OR (f.res<>done) THEN
   EXIT
  END;
  Bearbeite(ch)
 END;
 (* Close auf jeden Fall aufrufen *)
 Close(f)
END
\end{example}
\end{alltt}

Mit der Prozedur {\tt Lookup} wird ein Datei zum Lesen und/oder Schreiben
er"offnet. Der Parameter {\tt name} enth"alt den Namen der zu
er"offnenden Datei. Mit {\tt new} k"onnen Sie angeben, ob Sie eine
neue oder bestehende Datei er"offnen m"ochten. Hat {\tt new}
den Wert {\tt TRUE} und es existiert eine Datei mit dem angegebenen
Namen, so wird diese beim Er"offnen gel"oscht. Die Filevariable
wird dem Ausgang der Operation entsprechend mit Werten belegt.

Die Daten einer Datei werden zwischengespeichert. So resultieren
mehrere Lesebefehle mit nur einem auf der Datei. Analog dazu
werden Schreibbefehle erst dann auf dem Dateisystem ausgef"uhrt,
wenn der zur Pufferung verwendete Puffer "uberlaufen w"urde.
Die Gr"osse des verwendeten Puffers wird beim {\tt Lookup}-Befehl
mit dem Parameter {\tt buffer} gesteuert. Wird keine Pufferung
gew"unscht, kann daf"ur auch 0 "ubergeben werden.

{\tt Close} schliesst eine zuvor mit {\tt Lookup} er"offnete
Datei. Noch im Puffer verbliebene Daten werden vorher noch
auf die Datei geschrieben.

{\tt Delete} l"oscht die angegebene Datei. Damit der Parameter
initialisiert ist, muss die Datei zuerst ge"offnet werden.

Mit {\tt SetPos} kann an eine beliebige Position innerhalb
der Datei gesprungen werden. Es kann nicht "uber das aktuelle
Dateiende positioniert werden; ein solcher Aufruf f"uhrt
zu einem Fehler. Nach einem Fehler ist der Zustand einer
Filevariablen undefiniert. Es ist im allgemeinen nicht
m"oglich, mit dieser Datei weiter zu arbeiten.
Das Feld {\tt res} darf {\em nicht\/} auf {\tt done} 
zur"uckgesetzt werden.

{\tt GetPos} gibt die aktuelle Position innerhalb der Datei
zur"uck.

{\tt Length} gibt die aktuelle Dateil"ange zur"uck. Dies ist zugleich
der h"ochste zul"assige Wert, der bei {\tt SetPos} verwendet werden darf.

{\tt ReadChar} und {\tt WriteChar} sind die Prozeduren zum Lesen
und Schreiben einzelner Zeichen.

{\tt ReadByteBlock} und {\tt WriteByteBlock} sind Prozeduren, die vor
allem dann ihren Einsatz finden, wenn beliebige Variablen
eines strukturierten Typs gelesen oder geschrieben werden sollen.

{\tt ReadBytes} und {\tt WriteBytes} arbeiten "ahnlich wie
{\tt ReadByteBlock} und {\tt WriteByteBlock}. Der Datenbereich
wird hier "uber die Adresse {\tt adr} und die L"angenangabe
{\tt len} angesprochen. Der Parameter {\tt actual} gibt an,
wieviele Byte gelesen beziehungsweise geschrieben werden konnten.

\subsection{Erkennen des Dateiendes bei Leseoperationen}

Das Feld {\tt eof} erh"alt den Wert {\tt TRUE}, wenn eine
Leseoperation genau hinter dem letzten g"ultigen Byte
der Datei gestartet wird. Eine Leseoperation, die {\tt eof}
setzt, kann deshalb nie g"ultige Daten von der Datei lesen,
obwohl {\tt res} auf dem Wert {\tt done} verbleibt.
Wenn das Dateiende w"ahrend einer Leseoperation
{\tt ReadBytes} oder {\tt ReadByteBlock} erreicht wird,
bleibt {\tt eof} auf {\tt FALSE}. Der Resultatswert
{\tt res} einer solchen Leseoperation ist abh"angig
von der verwendeten Methode.

\begin{ttscript}{ReadByteBlock}
\item[ReadBytes]
  Da {\tt ReadBytes} die Anzahl der gelesenen Byte immer
  angibt, k"onnen beim Dateiende zwei F"alle auftreten:
  \begin{enumerate}
  \item
    In der Datei sind zwischen einem und Blockgr"osse
    Byte bis zum Dateiende vorhanden. Diese werden in den
    Block eingelesen und die aktuelle L"ange wird entsprechend gesetzt.
    \begin{quote} \tt
    eof = FALSE \\
    res = done
    \end{quote}
  \item
    Die Datei wurde bereits vollst"andig gelesen. Das Dateiende
    ist erreicht, {\tt eof} ist wahr und der Lesezugriff ist
    erfolgreich.
    \begin{quote} \tt
    eof = TRUE \\
    res = done
    \end{quote}
  \end{enumerate}
\item[ReadByteBlock]
  Die Prozedur {\tt ReadByteBlock} kennt keine M"oglichkeit, unvollst"andige
  Bl"o"cke anzuzeigen. Dadurch ergibt sich ein von {\tt ReadBytes}
  unterschiedliches Verhalten:
  \begin{enumerate}
  \item
    In der Datei sind zwischen einem und Blockgr"osse-1 Byte
    bis zum Dateiende vorhanden. Ein unvollst"andiger
    Block ist jedoch kein g"ultiges Resultat dieser
    Operation, der Inhalt des Blocks ist undefiniert.
    \begin{quote} \tt
    eof = FALSE \\
    res = notdone
    \end{quote}
  \item
    Das Dateiende wurde bereits vollst"andig gelesen. Das Dateiende
    ist erreicht, {\tt eof} ist wahr und der Lesezugriff ist erfolgreich.
    \begin{quote} \tt
    eof = TRUE \\
    res = done
    \end{quote}
  \end{enumerate}
\end{ttscript}

\newpage

\section{FPUExc}

Das Modul dient zur Steuerung des Verhaltens einer FPU 68881/882
be"-z"ug\-lich Fehlern und Rundung von Zahlen.
Es kann auch ohne vorhandene FPU problemlos importiert und
benutzt werden. Darum sollte es auch dann importiert werden, wenn
nicht speziell Code fuer eine FPU generiert wird.
Es erlaubt die Einstellung, welche Fehler zu einer Exception,
also zu einem Laufzeitfehler --- in der Amiga-Terminologie ein Trap ---
f"uhren.

Normalerweise ist die FPU vom Betriebssystem so eingestellt,
dass nicht korrekte Berechnungen,
beispielsweise "Uberlauf oder Wurzel aus einer
negativen Zahl, keine Auswirkungen auf den Programmablauf
haben. Das Programm arbeitet danach einfach mit nicht vorhersehbaren
und im allgemeinen unsinnigen Werten weiter.
Durch den Import dieses Moduls wird die FPU so initialisiert,
dass inkorrekte Resultate solcher Berechnungen 
zu einem Laufzeitfehler f"uhren.

Zus"atzlich zu diesem rein passiven Verhalten bietet das Modul
eine Reihe von Prozeduren, die es dem Kenner der Materie
erlauben, das Verhalten der FPU seinen W"unschen entsprechend
einzustellen. Dazu empfiehlt aber unbedingt das Studium
der Fachliteratur von Motorola.

{\tt EnableExc} 
behandelt die durch die Konstante {\tt stdExc} definierten Exceptions.

{\tt DisableExc} schaltet die Behandlung aller Exceptions ab.

Die Prozeduren {\tt SetExc} und {\tt ClearExc}
erlauben das Setzen oder L"oschen einzelner Exceptions.

Sollen gleich mehrere Exceptions behandelt beziehungsweise
ignoriert werden, kann dies mit der Prozedure
{\tt SetExcSet} geschehen. Damit werden {\em genau\/} die
im SET {\tt fpuExcSet} enthaltenen Exceptions behandelt.

Die behandelten Exceptions liefert die Funktion
{\tt GetExcSet} zur"uck.

Der Rundungsmodus der FPU kann ebenfalls ge"andert werden.
Der aktuelle Rundungsmodus kann mit 
{\tt GetRounding} festgestellt werden, w"ahrend 
{\tt SetRounding} den in {\tt roundingMode} angegebenen Modus 
setzt.

\newpage

\section{GfxMacros}

{\tt AreaCircle} ruft {\tt AreaEllipse} auf,
wobei als L"ange der beiden Halbachsen
der Kreisradius eingesetzt wird.

Die vier {\tt C\cmsltt cmd\/} Prozeduren
vereinfachen die Manipulation von Copperlisten.

{\tt CINIT} alloziert und initialisiert die Copperlisten-Puffer innerhalb einer
{\tt UCopList}. {\tt n} gibt die maximale Zahl von Copperlist-Befehlen an.

{\tt CMOVE} f"ugt einen Move-Befehl in die Copperliste ein.
{\tt a} enth"alt die Adresse
des Hardwareregisters und {\tt b} den Wert, der dort abgespeichert werden soll.

{\tt CWAIT} f"ugt einen Wait-Befehl in die Copperliste ein.
{\tt v} und {\tt h} enthalten die
vertikale und horizontale Bildschirmposition.

{\tt CEND} f"ugt den richtigen Wait-Befehl ein,
um die Copperliste abzuschliessen.

{\tt DrawCircle} ruft {\tt DrawEllipse} auf,
wobei als L"ange der beiden Halbachsen
der Kreisradius eingesetzt wird.

{\tt RemBob} markiert ein Blitter-Object so,
dass es beim n"achsten Aufruf von
{\tt DrawGList} aus der Liste der aktiven Grafikelemente (Gels) entfernt wird.

{\tt RasSize} rechnet aus, wieviele Byte
f"ur eine Bitplane der H"ohe {\tt h} und
Breite {\tt w} ben"otigt werden.

{\tt OnDisplay} und {\tt OffDisplay} schalten die Bildschirmanzeige
ein bzw.\ aus, indem
sie das DMA-Register manipulieren.

{\tt OnSprite} und {\tt OffSprite} schalten die Sprites ein bzw.\ aus.
Bei ausgeschalteten
Sprites ist nat"urlich auch der Mauszeiger nicht mehr sichtbar.

{\tt OnVBlank} und {\tt OffVBlank} schalten den
Vertical Blank Interrupt ein bzw.\ aus, indem
sie das Interrupt-Register manipulieren.

{\tt SetOPen} schaltet den Modus ein,
indem mit {\tt Area\cmsltt graph} definierte Fl"a"-chen mit einem
Rand versehen werden und definiert die Farbe des Randes.
Ein Aufruf von {\tt BndryOff} schaltet
diesen Modus wieder aus.

{\tt SetDrPt} definiert das Muster,
dass beim Zeichnen einer Linie verwendet wird.

{\tt SetAfPen} definiert das Muster,
dass beim Zeichnen von Fl"achen benutzt wird.

\newpage

\section{Heap}

Das Modul {\tt Heap} stellt die f"ur dynamische Speicher-Allozierung und
Deallozierung ben"otigten Prozeduren zur Verf"ugung. Es beh"alt die Kontrolle
"uber alle allozierten Speicherbereiche und gibt sie im Falle eines
Programmabsturzes oder am Programmende wieder frei.

Das Modul Heap bietet eine einfache Schnittstelle zu den Funktionen der
Speicherverwaltung des Betriebssystems. Es werden die Exec-Funktionen
{\tt AllocMem}, {\tt FreeMem}
und {\tt AvailMem} verwendet. Die durch Prozeduren des Moduls {\tt Heap}
angeforderten Speicherbl"ocke werden in einer Liste vermerkt. Dies erm"oglicht
sp"ater die Freigabe der allozierten Speicherbereiche. Die Verkettung
ben"otigt etwas zus"atzlichen Speicher (8 Byte) und Zeit.

Folgende Informationen werden umnmittelbar {\em vor\/} dem allozierten Block
abgelegt:

\begin{alltt}
  next: ADDRESS; (* Zeiger auf folgenden Block oder NIL *)
  size: LONGINT; (* Gr"osse des Blocks *)
\end{alltt}

Die Prozedur {\tt Allocate} alloziert einen Bereich der in Byte
angegebenen Gr"osse {\tt size} und weist dessen Adresse dem Parameter
{\tt adr} zu. Ist der Parameter {\tt size} negativ, so bricht das
aufrufende Programm mit einem Laufzeitfehler ab. Ist nicht mehr gen"ugend
Speicher vorhanden, erh"alt {\tt adr} den Wert {\tt NIL}. Ein
erfolgreich angeforderter Speicherblock wird mit Nullen gef"ullt.

{\tt Deallocate} gibt einen zuvor mit {\tt Allocate} oder {\tt AllocMem}
angeforderten Speicherbereich wieder frei und weist dem angegebenen
Zeiger den Wert {\tt NIL} zu.
Weist der Zeiger auf keinen durch {\tt Heap} reservierten
Speicher, wird der Aufruf ignoriert.

{\tt Available} gibt die Gr"osse des gesamten freien Speicherplatzes
zur"uck. Ist der Parameter {\tt chipMem} auf {\tt FALSE} gesetzt, wird die
Speichergr"osse in Chip- und Fast-Memory zusammen, sonst nur diejenige
in Chip-Memory angegeben.

{\tt Largest} gibt die gibt die Gr"osse des gr"ossten, zusammenh"angenden
Speicherbereiches zur"uck. F"ur den Parameter {\tt chipMem} gilt das gleiche
wie bei {\tt Available}.

Die Prozedur {\tt AllocMem} ist eine Variante der {\tt Allocate}-Prozedur.
Der Parameter {\tt chipMem} gibt an, ob der Speicher im Chip-Memory
alloziert werden soll, oder ob der Typ des Speichers gleichg"ultig
ist;  er kann dann Fast- oder Chip-Memory sein. In jedem Fall wird der
Speicherbereich mit Nullen initialisiert.

{\tt BlockSize} ist eine Hilfsfunktion, die es erlaubt, nachtr"aglich
die Gr"osse eines Speicherbereiches abzufragen. Wurde der Bereich nicht
durch das Modul {\tt Heap} angefordert, wird der Wert 0 zur"uckgegeben.

\begin{warning}
Greifen Sie nie auf einen Zeiger zu, dessen Speicherbereich nicht
alloziert oder bereits dealloziert wurde! Ein Absturz ist damit
garantiert! Verwenden Sie {\tt Storage} (Seite \pageref{Storage})
anstelle von {\tt Heap},
wenn Sie keine Ausnahmebehandlungen vorsehen wollen.
\end{warning}

\begin{note}
Aus Gr"unden der Portabilit"at sollte --- wenn m"oglich --- {\tt Allocate}
der Prozedur {\tt AllocMem} vorgezogen werden.
\end{note}

\newpage

\section{InOut}

Das Modul {\tt InOut} ist ein Standard-Modul f"ur formatierte
Ein- und Ausgabe auf den Bildschirm oder auf Dateien. Die prim"are
Ein- und Ausgabe geschieht "uber die Ein- und Ausgabestr"ome wie im
Abschnitt Terminal (Seite \pageref{Terminal}) beschrieben, beide k"onnen
jedoch auf Dateien umgelenkt werden. Dieses Umlenken ist unabh"angig
von der Umlenkm"oglichkeit von AmigaDOS.

{\tt OpenInput} und {\tt OpenOutput} lesen beide einen Dateinamen
von der Tastatur --- durch einen Aufruf von {\tt Terminal.Read}
und "offnen eine Ein-, beziehungsweise
Ausgabedatei. Die Variable {\tt done} enth"alt nach erfolgreicher
Er"offnung den Wert {\tt TRUE}. Endet der eingegebene Name mit einem
Punkt ("`{\tt .}"'), wird die Zeichenkette {\tt defExt} an den
Dateinamen angeh"angt.

{\tt SetInput} und {\tt SetOutput} "offnen ebenfalls eine
Ein-, beziehungswseise Ausgabedatei. Allerdings muss hier
der {\em volle\/} Dateiname "ubergeben werden und es wird
{\em keine\/} Eingabe vom Benutzer erwartet.

{\tt CloseInput} und {\tt CloseOutput} schliessen eine zuvor
er"offnete Ein- oder Ausgabedatei. Der Eingabestrom kommt von der
Tastatur und die Ausgabe geschieht wieder "uber den Bildschirm
({\tt Terminal.Read}, {\tt Terminal.Write}).

{\tt ReadString} liest eine Zeichenkette ein, d.h.\ eine Folge
von Zeichen, die weder Leerzeichen noch Kontrollzeichen enth"alt.
F"uhrende Leerzeichen werden ignoriert. Die Eingabe wird durch
jedes Kontrollzeichen oder ein leerzeichen ($\le$"`{\tt }"') beendet.
Soll ein Leerzeichen in die Zeichenkette eingef"ugt werden, muss
dieses in Anf"uhrungszeichen gesetzt werden (vgl. {\tt Argument},
Seite \pageref{Arguments}).

{\tt ReadInt}, {\tt ReadCard}, {\tt ReadLongInt} und {\tt ReadLongCard}
lesen eine Zeichenkette ein und wandeln diese entsprechend um.
F"uhrende Leerzeichen werden ignoriert.

{\tt ReadBytes} kann nur angewendet werden, wenn eine Eingabedatei
er"offnet wurde. Es werden soviele Byte gelesen, wie {\tt blk}
Platz bietet.

{\tt WriteInt}, {\tt WriteCard}, {\tt WriteOct} und {\tt WriteHex}
schreiben die "ubergebene Zahl {\tt x} mit mindestens {\tt n} Zeichen.
Sind nicht alle {\tt n} Zeichen mit Werten belegt, werden der
Zahl Leerzeichen ({\tt WriteInt}, {\tt WriteCard}) beziehungsweise
Nullen ({\tt WriteOct}, {\tt WriteHex}) vorangestellt.

{\tt WriteBytes} schreibt den gegebenen Block auf eine zuvor er"offnete
Ausgabedatei.

Die Variable {\tt termCh} enth"alt das Abschlusszeichen nach
einem Aufruf der Prozeduren {\tt ReadString}, {\tt ReadInt},
{\tt ReadLongInt}, {\tt ReadCard} und schliesslich {\tt ReadLongCard}.

\begin{note}
Solange Ein- und Ausgabe nicht explizit umgelenkt wurde --- durch
einen Aufruf
von {\tt OpenInput} oder {\tt OpenOutput} --- wird diese "uber
das Modul {\tt Terminal} abgewickelt. F"ur Informationen
"uber die im Modul {\tt Terminal} verwendeten Ein- und Ausgabekan"ale
muss im Abschnitt Terminal, Seite \pageref{Terminal},
nachgeschlagen werden.
\end{note}

\begin{note}
W"ahrend Sie {\tt INTEGER}-Werte durch die gleiche
Prozedur wie {\tt LONGINT}-Werte schreiben
k"onnen, wird f"ur deren Eingabe eine eigene Prozedur
ben"otigt. Dies kommt daher, dass bei Variablen-Parameter
die formalen und die aktuellen Parameter typenkompatibel
sein m"ussen. {\tt INTEGER} und {\tt LONGINT}
sind jedoch nur zuweisungskompatibel.
Die analoge Einschr"ankung gilt auch f"ur die Typen
{\tt CARDINAL} und {\tt LONGCARD}.
\end{note}

\begin{note}
Um die Wahl zwischen Ausgabe auf den Bildschirm oder auf Datei
w"ahlbar zu halten, sollte nach dem Aufruf von {\tt OpenOutput}
unbedingt die Variable {\tt termCh} abgefragt werden. Enth"alt
die Variable {\tt termCh} das Nullzeichen ({\tt 0C}), wurde ein
leerer Name eingegeben. Das Programm sollte dann normal fortgesetzt
werden.
\end{note}

\newpage

\section{IntuiMacros}

Diese Prozeduren helfen einen Code, der von Intuition bei
einer Menuauswahl liefert, zu zerlegen oder einen solchen
Code selbst aufzubauen.

{\tt MenuNum}, {\tt ItemNum} und {\tt SubNum} erwarten
einen Code und entnehmen
daraus die Menu-Nummer bzw.\ MenuItem-Nummer oder Subitem-Nummer.

{\tt ShiftMenu}, {\tt ShiftItem} und {\tt ShiftNum}
erwarten eine Menu-Nummer,
MenuItem-Nummer oder SubItem-Nummer und geben eine Zahl zur"uck,
bei der die Nummer an der richtigen Position im Codefeld ist.
Wenn man einen kompletten Code mit diesen Prozeduren aufbauen will,
dann muss man die einzelnen Werte addieren, wobei 0-Werte nicht zu
ber"ucksichtigen sind.

\begin{example}
Beispiel: Es soll ein Code erzeugt werden
mit Menu-Nummer 3 und der MenuItem-Nummer 4.
Die SubItem-Nummer wird nicht gebraucht und soll 0 sein.

\begin{quote}\tt
code:=ShiftMenu(3)+ShiftItem(4);
\end{quote}
\end{example}

\newpage

\section{LongRealConversions}

Das Modul {\tt LongRealConversions} stellt die Prozeduren zur
Umwandlung von Gleitpunktzahlen (Dezimalbr"uchen)
doppelter Genauigkeit zwischen interner
und lesbarer Darstellung und umgekehrt zur Verf"ugung.

Die Prozedur {\tt StrToReal} wandelt die in {\tt str}
gespeicherte Gleitpunktzahl in die interne LONGREAL-Darstellung um.
Enth"alt die Zeichenkette nicht erlaubte Zeichen, oder kann
die beschriebene Zahl nicht in einer LONGREAL-Variablen dargestellt
werden, erh"alt {\tt err} den Wert {\tt TRUE}.

Die Prozedur {\tt RealToStr} erlaubt vielseitige Umwandlungen
von {\tt r} in lesbare Darstellungsformen. Die resultierende
Zeichenkette enth"alt genau {\tt m} Zeichen, oder soviele
wie {\tt s} Platz bietet, falls {\tt m} zu gross ist.
Ist {\tt m} positiv, werden notwendige Leerzeichen
vor der Zahl angeh"angt, sonst werden sie angeh"angt. Die Anzahl
Zeichen hinter dem Dezimalpunkt wird durch {\tt n} gegeben. 
Falls in Ber"ucksichtigung zur Feldgr"osse
die Anzahl der Dezimalstellen zu gross gew"ahlt wurde, wird diese
auf das entsprechende Maximum gek"urzt. Ist {\tt n=0} wird
kein Dezimalpunkt geschrieben. Der Parameter {\tt expo} gibt an, ob die
wissenschaftliche Schreibweise (Exponentialdarstellung)
gew"unscht ist.

M"ogliche Fehlerquellen --- durch den Parameter {\tt err}
mitgeteilt --- sind ein negativer Wert von {\tt n},
der Wert Null f"ur {\tt m} oder {\tt s} beinhaltet zu wenig
Zeichen, um die resultierende Zeichenkette abzuspeichern.

\newpage

\section{LongRealInOut}

Dieses Modul entspricht dem Standardmodul {\tt RealInOut}
f"ur die Ein- und Ausgabe von Zahlen des Typs {\tt LONGREAL}.
Der Ein- und Ausgabestrom wird vom Modul {\tt InOut}
(Seite \pageref{InOut}) kontrolliert.

Die Prozedur {\tt WriteReal} schreibt die "ubergebene Zahl
{\tt r} in ein Feld der Gr"osse {\tt width}, wobei im Maximum {\tt dec}
Dezimalstellen geschrieben werden. F"ullt die Darstellung
das Feld nicht aus, wird dieses mit Leerzeichen ausgef"ullt.
Ist die Feldgr"osse positiv, werden die Leerzeichen vor der
Zahl gesetzt, sonst werden sie angeh"angt.

{\tt ReadReal} list eine Zeichenkette von der Eingabe
--- gegeben durch das Modul {\tt InOut} --- und wandelt
diese in die {\tt LONGREAL}-Zahl {\tt r} um.

\newpage

\section{MathLib0}

Standard-Modul f"ur einige transzendente Funktionen. Weitere
Funktionen sind direkt auf diesen aufbaubar.

Die Einheit der Argumente der Funktionen {\tt sin} und {\tt cos}
sowie des Resultats der Funktion {\tt arctan} ist das Bogenmass
(Radiant Abk"urzung rad). Dabei gilt folgende Formel:
$$ 1 rad = \frac{180^{\circ}}{\pi} $$

{\tt ln} gibt den nat"urlichen Logarithmus (Basis $e$) von {\tt x}
zur"uck.

\begin{warning}
Funktionsaufrufe mit Argumenten, deren Resulatswert nicht definiert
ist --- beispielsweise Quadratwurzeln oder Logarithmen negativer
Zahlen --- f"uhren zum Abbruch des Programms.
\end{warning}

\begin{example}
Beispiele f"ur aufbauende Funktionen:
\begin{verbatim}
PROCEDURE tan(x:REAL):REAL;
BEGIN
 RETURN sin(x)/cos(x)
END tan;

PROCEDURE log(x:REAL):REAL;
BEGIN
 RETURN ln(x)/ln(10)
END log;

PROCEDURE Rad2Angle(rad:REAL):REAL;
BEGIN
 RETURN rad*180.0/pi
END Rad2Angle;

PROCEDURE Angle2Rad(angle:REAL):REAL;
BEGIN
 RETURN angle*pi/180.0
END Angle2Rad;
\end{verbatim}
\end{example}

Die analogen Beispiele gelten auch f"ur die Moduln {\tt MathLibFFP}
und {\tt MathLibLong}. Da die Liste der bekanntesten transzendenten
Funktionen bereits sehr gross ist, selten jedoch wirklich viele
gebraucht werden, wurde auf die Definition weiterer
\mbox{{\tt MathLib}\ldots}-Moduln verzichtet. Obige Beispiele
zeigen, dass die Definition zus"atzlicher Moduln keine Schwierigkeiten
bereiten sollte.

\newpage

\section{MathLibFFP}

Dieses Modul kommt zur Anwendung, wenn aus Gr"unden der Portabilit"at
das Schnittstellen-Modul {\tt MathTrans} nicht
verwendet werden soll. Es entspricht in der Funktionalit"at
dem Modul {\tt MathLib0}, verwendet jedoch f"ur alle
Argumente den Typ {\tt FFP}.

Die Einheit der Argumente der Funktionen {\tt sin} und {\tt cos}
sowie des Resultats der Funktion {\tt arctan} ist das Bogenmass
(Radiant Abk"urzung rad). Dabei gilt folgende Formel:
$$ 1 rad = \frac{180^{\circ}}{\pi} $$

{\tt ln} gibt den nat"urlichen Logarithmus (Basis $e$) von {\tt x}
zur"uck.

\begin{warning}
Funktionsaufrufe mit Argumenten, deren Resulatswert nicht definiert
ist --- beispielsweise Quadratwurzeln oder Logarithmen negativer
Zahlen --- f"uhren zum Abbruch des Programms.
\end{warning}

\begin{example}
Beispiel f"ur einen Modulaufbau einer m"oglichst
portablen Applikation:
\begin{alltt}
MODULE mlffp;

FROM MathLibFFP IMPORT  (* !! *)
 e, pi,
 sqrt, exp, ln, sin, cos, arctan;
 
TYPE REAL = FFP;         (* !! *)

VAR
 r1, r2: REAL;

BEGIN
{\rm\ldots}
\end{alltt}
Im obigen Beispiel m"ussen nur die beiden mit
{\tt (* !! *)} markierten Zeilen ge"andert werden,
falls der Typ {\tt FFP} nicht vorhanden ist.
\end{example}

\newpage

\section{MathLibLong}

Standard-Modul f"ur einige transzendente Funktionen.
Diese Funktionen arbeiten mit dem Typ {\tt LONGREAL}.

Die Einheit der Argumente der Funktionen {\tt sin} und {\tt cos}
sowie des Resultats der Funktion {\tt arctan} ist das Bogenmass
(Radiant Abk"urzung rad). Dabei gilt folgende Formel:
$$ 1 rad = \frac{180^{\circ}}{\pi} $$

{\tt ln} gibt den nat"urlichen Logarithmus (Basis $e$) von {\tt x}
zur"uck.

\begin{warning}
Funktionsaufrufe mit Argumenten, deren Resulatswert nicht definiert
oder zu gross sind --- beispielsweise {\tt sqrt(-1.0)} oder
{\tt exp(720.0)} --- f"uhren {\em nicht\/} zum Programmabbruch.
Es wird mit falschen Werten weitergerechnet.

Ein Abbruch in diesen F"allen ist nur m"oglich,
wenn Sie einen 6888x-Coprozessor haben.
Dann gen"ugt ein blosser Import des Moduls {\tt FPUExc}
(Seite \pageref{FPUExc}).
\end{warning}

\begin{note}
Falls sie eine FPU (6888x-Coprozessor) besitzen, k"onnen sie
obenstehende Funktionen auch direkt durch diese ausf"uhren lassen.%
\footnote{Dies reduziert die Codegr"osse und verschnellert das Programm.}
Verwenden Sie dabei die entsprechenden Funktionen aus dem
Pseudomodul {\tt SYSTEM}, beschrieben im Abschnit \ref{SysMod},
Seite \pageref{SysMod}.
\end{note}

\newpage

\section{R}

Das Modul {\tt R} definiert Konstanten f"ur die Register der 68000-CPU
und der 68881-FPU. Durch die Benutzung dieser Konstanten werden eine
gute Lesbarkeit der Quelltexte erreicht und Fehler vermieden.

\noindent
Der Compiler erwartet Register-Konstanten in folgenden F"allen:
\begin{itemize}
\item {\tt SYSTEM.REG} (nur {\tt D0}\ldots{\tt A7} erlaubt)
\item {\tt SYSTEM.SETREG} (nur {\tt D0}\ldots{\tt A7} erlaubt)
\item {\tt SYSTEM.LOADREGS} (nur {\tt D0}\ldots{\tt A7} erlaubt)
\item {\tt SYSTEM.SAVEREGS} (nur {\tt D0}\ldots{\tt A7} erlaubt)
\item Register-Variablen und -Parameter.
\end{itemize}

\begin{example}
\noindent
Einige Beispiele:
\begin{verbatim}
  IMPORT R;

  SYSTEM.SETREG(R.D1,longintval)
  longintval:=SYSTEM.REG(R.D5)
  SYSTEM.SAVEREGS({R.D0,R.D1,R.A0,R.A1});

  PROCEDURE float(longr{R.FP3}:LONGREAL;
                  VAR val{R.A0}:SHORTINT);

  VAR bool{R.D7}:BOOLEAN;
\end{verbatim}
\end{example}

\newpage

\section{RandomNumber}

Dieses Modul generiert Pseudo-Zufallszahlen, wie sie in
Spielprogrammen oder Simulationen ben"otigt werden.
Dabei wird immer von einem Ausgangswert aus eine
Zufallszahl sowie ein neuer Ausgangswert erzeugt.

{\tt Random} gibt eine Pseudo-Zufallszahl im Bereich von
0 bis 1 (\verb'[0,1[') zur"uck. Die erzeugten Zahlen sind
gleichm"assig "uber diesen Bereich verteilt. Mit dem vorgegebenen 
Startwert betr"agt die Periode mindestens $2^{32}-1$.

Die Funktion {\tt RND} gibt eine ganze Zahl zwischen 0 und
{\tt nr-1} --- beziehungsweise {\tt nr+1} f"ur negative {\tt nr}) ---
zur"uck. Ein W"urfel w"urde folgendermassen simuliert:
\begin{example} \tt
wurf:=1+RND(6);
\end{example}

{\tt GetSeed} weist dem Parameter {\tt seed} den aktuellen Ausgangswert
zu.

{\tt PutSeed} setzt ein neuen Ausgangswert. Dieser muss positiv
und ungleich Null sein.

\newpage

\section{RealConversions}

Das Modul {\tt RealConversions} stellt die Prozeduren zur
Umwandlung von Gleitpunktzahlen (Dezimalbr"uchen)
zwischen interner
und lesbarer Darstellung und umgekehrt zur Verf"ugung.

Die Prozedur {\tt StrToReal} wandelt die in {\tt str}
gespeicherte Gleitpunktzahl in die interne REAL-Darstellung um.
Enth"alt die Zeichenkette nicht erlaubte Zeichen, oder kann
die beschriebene Zahl nicht in einer REAL-Variablen dargestellt
werden, erh"alt {\tt err} den Wert {\tt TRUE}.

Die Prozedur {\tt RealToStr} erlaubt vielseitige Umwandlungen
von {\tt r} in lesbare Darstellungsformen. Die resultierende
Zeichenkette enth"alt genau {\tt m} Zeichen, oder soviele
wie {\tt s} Platz bietet, falls {\tt m} zu gross ist.
Ist {\tt m} positiv, werden notwendige Leerzeichen
vor der Zahl angeh"angt, sonst werden sie angeh"angt. Die Anzahl
Zeichen hinter dem Dezimalpunkt wird durch {\tt n} gegeben. 
Falls in Ber"ucksichtigung zur Feldgr"osse
die Anzahl der Dezimalstellen zu gross gew"ahlt wurde, wird diese
auf das entsprechende Maximum gek"urzt. Ist {\tt n=0} wird
kein Dezimalpunkt geschrieben. Der Parameter {\tt expo} gibt an, ob die
wissenschaftliche Schreibweise (Exponentialdarstellung)
gew"unscht ist.

\begin{example}
\begin{alltt}
r:=12.976;
RealToStr(r,str,5,2,FALSE,err);
  (* str: "`12.98"'
     err: FALSE *)
RealToStr(r,str,4,2,FALSE,err);
  (* str: "`13.0"'
     err: FALSE *)
RealToStr(r,str,3,2,FALSE,err);
  (* str: "` 13"'
     err: FALSE *)
RealToStr(r,str,2,2,FALSE,err);
  (* str: "`13"'
     err: FALSE *)
RealToStr(r,str,1,2,FALSE,err);
  (* str: {\rm undefiniert}
     err: TRUE *)
RealToStr(r,str,-8,2,FALSE,err);
  (* str: "`12.98   "'
     err: FALSE *)
RealToStr(r,str,10,2,TRUE,err);
  (* str: "`  1.30E+01"'
     err: FALSE *)
\end{alltt}
\end{example}

M"ogliche Fehlerquellen --- durch den Parameter {\tt err}
mitgeteilt --- sind ein negativer Wert von {\tt n},
der Wert Null f"ur {\tt m} oder {\tt s} beinhaltet zu wenig
Zeichen, um die resultierende Zeichenkette abzuspeichern.

\newpage

\section{RealInOut}

Standardmodul f"ur die Ein- und Ausgabe von Zahlen des Typs {\tt REAL}.
Der Ein- und Ausgabestrom wird vom Modul {\tt InOut}
(Seite \pageref{InOut}) kontrolliert.

Die Prozedur {\tt WriteReal} schreibt die "ubergebene Zahl
{\tt r} in ein Feld der Gr"osse {\tt width}, wobei im Maximum {\tt dec}
Dezimalstellen geschrieben werden. F"ullt die Darstellung
das Feld nicht aus, wird dieses mit Leerzeichen ausgef"ullt.
Ist die Feldgr"osse positiv, werden die Leerzeichen vor der
Zahl gesetzt, sonst werden sie angeh"angt.

{\tt ReadReal} list eine Zeichenkette von der Eingabe
--- gegeben durch das Modul {\tt InOut} --- und wandelt
diese in die REAL-Zahl {\tt r} um.

\newpage

\section{Scan}

Die Prozedur {\tt ScanString} liest eine Zeichenkette ein
und speichert diese im Parameter {\tt str}. F"uhrende Leerzeichen
werden "ubersprungen. Die leseprozedur muss dazu "ubergeben werden.
Der Lesevorgang der Zeichenkette wird durch ein Leerzeichen oder
{\em jedes\/} Kontrollzeichen ({\tt ch$\le$"`\verb*/ /"'}) beendet.
Soll ein Leerzeichen in die Zeichenkette eingef"ugt
werden, muss dieses in Anf"uhrungszeichen ("') gesetzt werden.
Das letztgelesene Zeichen wird in {\tt ch} gespeichert,
die L"ange der Zeichenkette in {\tt len}.

\newpage

\section{SeqIo}

Das Modul {\tt SeqIo} bietet Prozeduren zur Dateibehandlung an.
Diese Prozeduren wurden speziell f"ur das sequentielle Lesen und
Schreiben von Dateien geschrieben. Bei Programmende werden alle
noch offenen Dateien geschlossen.

Eine existierende Datei wird mit {\tt OpenSeqIn} f"ur das
sequentielle Lesen ge"offnet. Die Puffergr"osse, die beim "Offnen
angegeben wird, muss durch 4 teilbar  und nicht 0 sein.

Von einer mit {\tt OpenSeqIn} ge"offneten Datei kann mit den
{\tt SeqIn\ldots} und {\tt SeqGet\ldots} Prozeduren 
gelesen werden. Die Prozeduren {\tt SeqInLQuick} und {\tt SeqGetLQuick}
d"urfen aber nur dann verwendet werden, wenn w"ahrend der
ganzen Dateibearbeitung nur
Langworte oder Vielfache
davon gelesen werden.

Mit {\tt OpenSeqOut} wird eine Datei f"ur das sequentielle
Schreiben ge"offnet. Auf die Datei kann dann mit den {\tt
SeqOut\ldots} Prozeduren geschrieben werden.

{\tt SeqOk} liefert den Wert {\tt TRUE}, wenn die bisherigen Lese- oder
Schreiboperationen erfolgreich waren. Im Fehlerfall kann dennoch
von der Datei gelesen, beziehungsweise auf die Datei geschrieben werden. Beim
Lesen erh"alt man immer den Wert 0. Beim Schreiben werden die
"ubergebenen Daten ignoriert.

{\tt CloseSeq} schliesst ein ge"offnete Datei. Alle ge"offneten
Dateien m"ussen geschlossen werden, auch dann, wenn {\tt SeqOk}
nach einer Schreib- oder Leseoperation einen Fehler gemeldet hat.

\newpage

\section{Storage}

Dieses Standardmodul stellt die zur dynamischen Speicherverwaltung
notwendigen Prozeduren zur Verf"ugung. Es beh"alt die Kontrolle
"uber alle allozierten Speicherbereiche und gibt sie im Falle
eines Programmabsturzes oder am Programmende wieder frei.

Prozedur {\tt ALLOCATE} alloziert einen Bereich der in Byte
gegebenen Gr"osse und weist dessen Adresse dem Parameter {\tt adr}
zu. Ist nicht gen"ugend Speicher vorhanden, bricht das aufrufende
Programm mit einem Laufzeitfehler ab.

{\tt DEALLOCATE} gibt einen zuvor allozierten Bereich an der Adresse
{\tt adr} wieder frei. Der "ubergebene Zeiger erh"alt den
Wert {\tt NIL}. Um mit gebr"auchlichen Versionen kompatibel zu bleiben,
muss die Gr"osse "ubergeben werden, der Wert
wird allerdings ignoriert.

Die Funktion {\tt Available} gibt den Wert {\tt TRUE} zur"uck,
falls ein Speicherbereich der gew"unschten Gr"osse zur
Verf"ugung steht.

\newpage

\section{String}

Das Modul {\tt String} bietet Manipulationsprozeduren
f"ur Zeichenketten an.
Alle Prozeduren h"angen ein Nullzeichen an
die resultierende Zeichenkette an.
Ausserdem existieren Pr"uf"|funktionen, die es dem Programmierer
erlauben, die fehlerfreie Ausf"uhrung der entsprechenden
Prozeduren zu garantieren.

Dieses Modul stellt die wichtigsten Prozeduren zur Manipulation
von Zeichenketten zur Verf"ugung. Alle entscheidenden Routinen wurden in
Assembler programmiert, um m"oglichst kompakt und schnell
zu sein. Die Kompaktheit einer solchen Implementation
ist aus der Gr"osse der Objektdatei leicht ersichtlich.

Die Prozeduren verwenden wenn m"oglich Werteparameter.
Dies er"-m"og\-licht die "Ubergabe konstanter Zeichenketten,
was jedoch nicht immer ef"|fizient ist:

\begin{example}
\begin{alltt}
CONST
 halloWelt = "Hallo Welt";
(*
  Nun gilt folgende Gleichung:
  Length(halloWelt) = SIZE(halloWelt)
*)
\end{alltt}
\end{example}

Entgegen der normalen Behandlung von Werteparametern werden von
den "ubergebenen Zeichenketten {\em keine\/} lokalen Kopien
erstellt. Dadurch erreicht man dieselbe Ef"|fizienz, die mit
Variablen-Parametern erreicht werden kann. Bei den
Prozeduren {\tt Copy}, {\tt CopyPos} und {\tt Concat}
kann dies aber zu Problemen f"uhren,
falls innerhalb der Zeichenkette umkopiert werden soll (siehe
untenstehendes Beispiel).

Die Funktionen {\tt Length} und {\tt LLength} geben die Anzahl
der Zeichen in {\tt str}
zur"uck. Ein abschliessendes Nullzeichen wird nicht gez"ahlt.
Es gilt also immer folgende Ungleichung:
$$ 0 \le {\tt Length(\cmsltt string\/\tt)} \le
{\tt HIGH(\cmsltt string\/\tt)} + 1 $$

Aufrufe von {\tt CanCopyPos}, {\tt CanCopy}, {\tt CanConcat},
{\tt CanInsert}, {\tt CanCopyPart} und {\tt CanConcatChar}
ergeben immer den Wert {\tt TRUE}, wenn die geforderte Prozedur
so ausgef"uhrt werden kann, dass in der Zielzeichenkette 
noch ein abschliessendes Nullzeichen als Abschlusszeichen Platz hat.
Dies ist innerhalb der Modula-Umgebung keine Notwendigkeit,
ist aber meist f"ur Systemaufrufe zwingend.

Die Prozedur {\tt CopyPos} kopiert die Zeichen aus {\tt src}
in die Zeichenreihe {\tt dest}, wobei an der Stelle {\tt dest[destPos]}
begonnen wird. Die nachfolgenden Zeichen in {\tt src}
werden "uberschrieben. Ist die resultierende Zeichenkette zu lang,
wird der "uberz"ahlige Rest abgeschnitten.

Die Prozedur {\tt Copy} "uberschreibt die Zeichenkette {\tt dest}
mit dem Inhalt von {\tt src}. Es entspricht einem Aufruf von
{\tt CopyPos}, wobei {\tt destPos} zu {\tt 0} gesetzt ist.

{\tt Concat} h"angt die Zeichenkette {\tt src} an {\tt dest} an.
"Uberz"ahlige Zeichen werden abgeschnitten.

\begin{note}
Da auch f"ur Werteparameter {\em keine\/} lokalen Kopien erstellt
werden, sind Kopien innerhalb einer Zeichenkette problematisch:

\begin{example}\begin{alltt}
MODULE showString;

IMPORT Terminal,String;

VAR s1,s2,s3: ARRAY [0..15] OF CHAR;

BEGIN
  s1:="012345"; s2:="abcdef"; s3:="ABCDEF";
  String.Copy(s1,s1);
  String.CopyPos(s2,s2,3);
  String.Concat(s3,s3);
  Terminal.WriteString(s1);
  Terminal.WriteLn;
  Terminal.WriteString(s2);
  Terminal.WriteLn;
  Terminal.WriteString(s3);
  Terminal.WriteLn;
END showString.

\end{alltt}

Obiges Programm ergibt folgende Ausgabe:
\begin{alltt}
012345
abcabcabcabcabc
ABCABCABCABCABC
\end{alltt}

Die Prozeduren {\tt CopyPos} und {\tt Concat} kopieren die Zeichenkette
solange weiter, bis in der Zielzeichenkette der vorhandene Platz
aufgebraucht ist. Dies kommt daher, dass das abschliessende Nullzeichen
der Ursprungskette gleichzeitig das Abschlusszeichen der Zielkette ist;
letzteres wird aber mit der ersten Kopieraktion "uberschrieben.
\end{example}

\end{note}

{\tt Compare} vergleicht die Zeichenkette {\tt str1} mit der
Zeichenkette {\tt str2}. Ist das Resultat negativ, so ist
{\tt str2} kleiner, ist es Null, sind beide gleich, und ist
es positiv, so ist {\tt str2} gr"osser als {\tt str1}. Der
Absolutwert des zur"uckgegebenen Resultats gibt die Zeichenposition,
an der sich die beiden Zeichenketten unterscheiden, wobei das
erste Zeichen dem Wert eins entspricht.

Die Funktion {\tt FirstPos} sucht nach dem ersten Vorkommen
des Zeichens {\tt ch} innerhalb der Zeichenkette {\tt str},
dort startend bei der Position {\tt from}. Zur"uckgegeben
wird die Position des ersten Vorkommens, oder {\tt noOccur}
falls das Zeichen nicht gefunden wurde.

Die Funktion {\tt LastPos} sucht nach dem letzten Vorkommen
des Zeichens {\tt ch} innerhalb der Zeichenkette {\tt str}.
Gesucht wird bis zur Position {\tt to}. Zur"uckgegeben
wird die Position des letzten Vorkommens, oder {\tt noOccur}
falls das Zeichen nicht gefunden wurde.

{\tt CapString} wandelt alle Kleinbuchstaben der Zeichenkette
{\tt str} in die entsprechenden Grossbuchstaben um. Die Umwandlung
entspricht derjenigen der Funktion {\tt CAP()}, wird also
nur f"ur die Zeichen "`{\tt a}"'--"`{\tt z}"' ausgef"uhrt.

Die Funktion {\tt ANSICap} macht den Mangel der vordefinierten
Funktion {\tt CAP()} wett: sie wandelt {\em alle\/} Zeichen, also
insbesondere auch Umlaute oder andere nationale Sonderzeichen
in die entsprechenden Grossbuchstaben um.

In analoger Weise wandelt {\tt ANSICapString} alle Zeichen
der "ubergebenen Zeichenkette in ihre entsprechenden
Grossbuchstaben um.

Die Funktion {\tt Occurs} sucht nach dem Vorkommen von {\tt token}
in {\tt str}, wobei dort mit dem Zeichen an der Position {\tt from}
begonnen wird. Der Resultatswert entspricht der Position des ersten
gemeinsamen Zeichens, oder {\tt last} falls {\tt token} in {\tt str}
nicht enthalten ist. Ist der Parameter {\tt caseSens} wahr,
werden Gross- und Kleinbuchstaben als unterschiedlich betrachtet,
sonst als gleichbedeutend. Davon ausgenommen sind alle Zeichen
mit einem Ordinalwert gr"osser 127.

Die Prozedur {\tt Insert}
f"ugt die Zeichenkette {\tt token} links des Zeichens an der Position
{\tt at} in {\tt str} ein. Ist die resultierende Zeichenkette zu lang,
um abgelegt zu werden, wird diese entsprechend abgeschnitten. Falls
notwendig, d.h.\ falls \verb'at > Length(str)', werden der
Zeichenkette {\tt str} zuerst Leerzeichen angeh"angt.
Ist \verb'at = last', wird {\tt token} an {\tt str} angeh"angt.

{\tt Delete} l"oscht {\tt length} Zeichen aus {\tt str} heraus,
beginnend an der Stelle {\tt from}. Die dahinterliegenden
Zeichen rutschen nach.

{\tt CopyPart} kopiert eine Teilzeichenkette von {\tt source} nach
{\tt str}. Die Teilzeichenkette beginnt an der Stelle {\tt start}
und ist {\tt length} Zeichen lang. Zeichen, die hinter dem
letzten Zeichen von {\tt source} liegen,
werden nicht ber"ucksichtigt. Die sich ergebende Zeichenkette
wird analog zur Prozedur {\tt Insert} abgeschnitten,
falls der Platz nicht ausreichen sollte.

{\tt ComparePart} vergleicht die Teilzeichenkette von {\tt str},
beginnend an der Stelle {\tt start} und {\tt length} Zeichen lang,
mit der gegebenen Zeichenkette {\tt token}. Ist das Resultat negativ,
so ist {\tt token} kleiner, ist es Null, sind beide gleich, und ist
es positiv, so ist {\tt token} gr"osser als die Teilzeichenkette.
Der Absolutwert des zur"uckgegebenen Resultats gibt die Zeichenposition,
an der sich die beiden Zeichenketten unterscheiden,
wobei das erste Zeichen dem Wert eins entspricht.

Die Prozedur {\tt ConcatChar} erm"oglicht das einfache
Anh"angen eines einzelnen Zeichens {\tt ch} an die
Zeichenkette {\tt str}.

{\tt DeleteChar} l"oscht ein einzelnes Zeichen an der
Position {\tt pos} aus der Zeichenkette {\tt str}.
Es entspricht einen Aufruf {\tt Delete(str, pos, 1)}.

Die beiden letzten Funktion erlauben schliesslich die Umwandlung
von "`Bstrings"' in normale Zeichenketten und umgekehrt.
Bstrings sind Zeichenketten, die nicht mit einem Nullzeichen
abgeschlossen werden, sondern im ersten Zeichen die Anzahl der
g"ultigen Zeichen angeben. So schiebt die Prozedur 
{\tt BStrToStr} alle Zeichen um eine Stelle nach links und erg"anzt
daf"ur die Zeichenkette um ein Nullzeichen, w"ahrend
{\tt StrToBStr} alle Zeichen um eine Stelle nach hinten r"uckt
und daf"ur die L"ange im ersten Zeichen eintr"agt.

\newpage

\section{Terminal}

Das Bibliotheksmodul {\tt Terminal} bietet einige grundlegende
Prozeduren, um Zeichen und Zeichenketten von der Tastatur zu lesen
und auf dem Bildschirm auszugeben.

Das Modul {\tt Terminal} ber"ucksichtigt die Unterschiede, die sich
aus der Arbeitsumgebung ergeben. Wird das Programm, das das Modul
{\tt Terminal} importiert, vom CLI aufgerufen, l"auft die Ein- und
Ausgabe "uber das entsprechende CLI-Fenster oder eine vom
Benutzer angegebene Umleitung ({\tt Dos.Input}, {\tt Dos.Output}).
Wird dasselbe
Programm von der Workbench aus gestartet, wird zur Ein- und
Ausgabe ein Fenster ge"offnet.

{\tt Terminal} verwendet die Methode der {\bf gepufferten Ausgabe}.
Das bedeutet, die Zeichen werden nicht sofort ausgegeben, sondern
zun"achst in einem internen Puffer zwischengespeichert. Diese Methode
erh"oht die Geschwindigkeit betr"achtlich, da weit weniger Dos-Aufrufe
n"otig sind. Der Inhalt des Puffers wird ausgegeben, wenn:
\begin{itemize}
\item Der Puffer voll ist (fasst 128 Zeichen).
\item Ein Zeilenvorschub ausgegeben werden soll ({\tt ASCII.eol})
\item Die Prozedur {\tt Flush} aufgerufen wird
\item Die Prozedur {\tt Read} direkt oder indirekt "uber {\tt ReadLn}
  oder {\tt BusyRead} aufgerufen wird.
\item Das Programm endet.
\end{itemize}

\begin{warning}
Durch die Pufferung ergibt sich ein Problem: Sollen Zeichen auf dem
Bildschirm ausgegeben werden ---  ohne dass die aktuelle
Zeile beendet wird ---,
die der Bediener sofort sehen soll, so muss danach ein Aufruf an die Funktion
\begin{quote} \tt Flush \end{quote}
erfolgen, damit der Pufferinhalt ausgegeben wird.
\end{warning}
% ich bin doof!/bp H"atte doch eine Prozedur Flush vorsehen k"onnen!
% Warum sagt mir das keiner????
% Inzwischen haben wir es Dir gesagt/red

Die Variable {\tt waitCloseGadget} kann vom Programmierer beliebig
ver"-"an\-dert werden. Ist sie bei Programmende
{\tt TRUE} (Standardeinstellung),
und wurde das Programm von der Workbench gestartet, so erscheint
im Fenster die Meldung \begin{quote} \verb|<< RETURN >>| \end{quote}
Das Programm
wartet so lange, bis der Bediener die \keyret-Taste bet"atigt hat
und schliesst erst dann das Fenster.
Ist die Variable {\tt FALSE}, wird das Fenster sofort geschlossen.
Beim Start vom CLI hat {\tt waitCloseGadget} keine Bedeutung.

Die Prozedur {\tt Read} liest ein Zeichen ein. Am Ende der Eingabedatei wird
das Zeichen {\tt ASCII.eof} zur"uckgegeben. Dies ist n"otig, um das
Eingabeende bei Eingabeumleitung zu erkennen. Man beachte, dass von einem
Konsolenfenster die Eingabe erst empfangen werden kann, wenn die Zeile
mit \keyret abgeschlossen wurde!

In einem Konsolenfenster kann {\tt ASCII.eof} durch \keyctrl[$\backslash$] an
das Programm "ubergeben werden. Dies ist sinnvoll, um das Verhalten
bei Dateiende zu testen oder zu simulieren.

Die Prozedur {\tt BusyRead} ist aus Gr"unden der Kompatibilit"at zur
urspr"unglichen Definition von Terminal "ubernommen worden. Der Grundgedanke
von {\tt BusyRead} ist die Abfrage, ob im Eingabestrom Zeichen zur
"Ubernahme bereitstehen. In der "ublichen Umgebung eines Konsolenfensters
ist dies aber nicht m"oglich. Diese Implementation liest das n"achste
Zeichen von der Eingabe und weist es der Variablen {\tt ch} zu.
Ist kein Zeichen im Eingabestrom vorhanden, erh"alt {\tt ch} den Wert
{\tt ASCII.nul}. Somit ist es {\em nicht\/} m"oglich, das Dateiende
einer interaktiven Datei (Eingabe von \keyctrl[$\backslash$]) zu erkennen.
% Ich verstehe das auch nicht! bp
Falls die Eingabe mittels Eingabeumlenkung von
einer nicht-interaktiven Datei kommt, ist {\tt BusyRead} identisch
mit {\tt Read}.

Die Prozedur {\tt ReadLn} liest eine ganze Zeile vom Eingabestrom,
d.h.\ bis das Zeichen {\tt ASCII.eol} oder {\tt ASCII.eof} erreicht wird.
Die eingelesenen Zeichen werden in {\tt str} abgelegt. Ist in der
Variablen nicht gen"ugend Platz vorhanden, wird der "ubersch"ussige
Teil ignoriert und ist f"ur das Programm verloren. Die Zeichenkette
wird immer mit {\tt ASCII.nul} abgeschlossen. D"urfen keine
Zeichen verloren gehen, muss die Prozedur {\bf Read} verwendet werden.
Dem Parameter {\tt len} wird die L"ange der Zeichenkette zugewiesen.

{\tt Write} gibt ein einzelnes Zeichen aus.

{\tt WriteLn} gibt das Zeichen {\tt ASCII.eol} aus. Dadurch wird der
Cursor auf die erste Spalte der folgenden Zeile gesetzt.

Die Prozedur {\tt WriteString} gibt die "ubergebene Zeichenkette aus.
Die Zeichenkette {\em muss nicht} durch das Zeichen {\tt ASCII.nul}
abgeschlossen sein.

Die Prozedur {\tt Format} benutzt die Funktion {\tt RawDoFmt} der
exec.library. Dabei wird ein Formatstring "ubergeben, der festlegt,
wie die einzelnen Daten formatiert ausgegeben werden sollen, sowie
die Adresse der Daten. Die Daten m"ussen von gleicher Anzahl und in
der gleichen Reihenfolge im Speicher liegen wie die Formatangaben.
Auch die Anzahl der jeweils belegten Bytes muss "ubereinstimmen. Diese
speziellen Formatangaben beginnen immer mit einem "`{\tt \%}"'-Zeichen,
worauf einige optionale Angaben folgen, und enden mit einem
speziellen Zeichen, das die Art der Interpretation der Daten
bestimmt.

Die Daten legt man sinnvollerweise in einem Record
ab\footnote{Es sei denn, man
weiss genau, wie die einzelnen Variablen im Speicher angeordnet sind.
Ach ja, wissen Sie es schon f"ur die Folgeversionen des Compilers?},
bei einzelnen Objekten kann auch einfach deren Adresse
angegeben werden.

Man sollte sich aber {\em davor h"uten},  um beispielsweise
eine einzelne Zeichenkette mit "`{\tt \%s}"' anzugeben,
einfach {\tt ADR(str)} zu
schreiben. Richtig w"are {\tt ADR(ADR(str))}. Da dies aber nicht m"oglich ist,
sollte man hierzu die Prozedur {\tt FormatS} benutzen!

\noindent Syntax der Formatangaben:
\begin{quote}\small
\verb/"%" ["-"] ["0"] [ min ["." max] ] ["l"] "d"|"x"|"c"|"s"/
\end{quote}
\begin{itemize}
\item Das Zeichen "`{\tt -}"' gibt an, dass der Inhalt linksb"undig
 im angegebenen Feld ausgegeben wird.
\item Das Zeichen "`{\tt 0}"' bewirkt, dass der Rest des Feldes mit Nullen
statt mit Leerzeichen aufgef"ullt wird. Da normalerweise rechtsb"undig
formatiert wird, ergeben sich dadurch also f"uhrende Nullen, bei linksb"undiger
Formatierung macht dies wohl wenig Sinn.
\item "`{\tt min}"' ist eine Dezimalzahl und bestimmt die Mindestbreite
 des Feldes, in dem der Wert ausgegeben wird. Wird kein Minimal-Wert angegeben,
 so wird das Feld nur so gross wie n"otig.
\item "`{\tt max}"' ist ebenfalls eine Dezimalzahl, die --- durch einen
Punkt von "`{\tt min}"' getrennt --- die maximale Feldbreite angibt. Dieser
Wert ist nur bei der Ausgabe von Zeichenketten (\%s) sinnvoll und gibt somit
an, wieviele Zeichen dieser Zeichenkette h"ochstens ausgegeben werden.
\item "`{\tt l}"' zeigt an, dass der Wert in den Daten als Langwort
vorliegt. Andernfalls wird --- mit Ausnahme von
Zeichenketten ---  immer angenommen,
der Wert bestehe aus zwei Byte.
\end{itemize}
\begin{ttscript}{x}
\item[d] stellt den Wert als Dezimalzahl dar.
\item[x] stellt den Wert als Hexadezimalzahl dar.
\item[c] stellt den Wert als einzelnes Zeichen dar. Hier muss der Wert
  aber immer in einem Wort oder Langwort stehen!
\item[s] nimmt den Wert als Adresse einer mit 0C abgeschlossenen
  Zeichenkette.
Hier spielt die Angabe "`l"' keine Rolle.
\item[\%\%] ergibt das Prozentzeichen.
\end{ttscript}

\begin{example}
\noindent
Ein Beispiel:
\begin{verbatim}
  Rec.longint:=10;
  Rec.integer:=51;
  Rec.cardinal:=ORD("y");
  Rec.stringadr:=ADR("LMNOPQRST");
  Rec.longcard:=123;
  Format("ABC%03lx,%-3d%%,%2c,%3.3s%ldEnde\n",ADR(Rec));
  -->  "ABC00A,51 % , y,LMN123Ende"
       mit anschliessendem Zeilenvorschub.
\end{verbatim}
\end{example}

{\tt FormatNr} erlaubt die Ausgabe von berechneten Zahlen "uber die
Format-Prozedur. Dadurch muss der Wert des Ausdrucks nicht in einer
Variablen gespeichert werden.

Die Formatangabe f"ur {\tt FormatNr} muss {\em immer\/} ein "`{\tt l}"'
enthalten, da der Parameter der Prozedur vom Typ {\tt LONGINT} ist;
andernfalls erh"alt man fal\-sche Ausgaben!
\begin{verbatim}
  FormatNr("Das waren %ld Punkte!",v1*4+v2);
  --> "Das waren 234 Punkte!"
\end{verbatim}

Die Prozedur {\tt FormatS} erleichtert die Ausgabe von variablen
Zeichenketten innerhalb einer Meldung.
\begin{verbatim}
  FormatS("Heute ist %s, der",DayArr[today]);
  --> "Heute ist Dienstag, der"
  FormatS(" - %s\n",fileName);
  --> " - Terminal.mod"
      mit anschliessendem Zeilenvorschub.
\end{verbatim}

{\tt WriteInt} und {\tt WriteHex} geben eine Zahl {\tt x} in einem Feld
der Mindest-Breite {\tt ABS(n)} aus. Ist der Wert von {\tt n} negativ, wird
die Zahl linksb"undig formatiert, andernfalls rechtsb"undig.
{\tt WriteHex} gibt die Zahl hexadezimal mit
f"uhrenden Nullen aus, {\tt WriteInt} dezimal mit f"uhrenden (oder angeh"angten)
Leerzeichen.
\begin{verbatim}
  WriteInt(10,4)
  --> "  10"
  WriteInt(10,-4)
  --> "10  "
  WriteHex(10,4)
  --> "000A"
  WriteHex(10,-4)
  --> "A   "
  WriteInt(10,0)
  --> "10"
\end{verbatim}


\subsection{Verwendeter Ein- und Ausgabekanal}
Im Normalfall ist das von Terminal verwendete Fenster ein Konsolenfenster
(Console). Dadurch ergeben sich Unterschiede zu manchen
\mtwo-Umgebungen. W"ahrend es dort m"oglich ist, Eingaben unmittelbar
zu lesen, ist dies in einem Konsolenfenster nicht m"oglich. Ein Konsolenfenster
erlaubt die "Anderung der gesamten Eingabezeile solange, bis die Eingabe
mit \keyret\ abgeschlossen wird. Ein einzelnes Zeichen kann also nicht
eingelesen werden, bevor der Anwender die \keyret-Taste bet"atigt hat.

\begin{example}
\begin{verbatim}
PROCEDURE Ja(text: ARRAY OF CHAR):BOOLEAN;
VAR ch:CHAR;
BEGIN
  WriteString(text);
  Read(ch);
  RETURN CAP(ch)="J"
END Ja;
\end{verbatim}
\noindent In diesem Beispiel bleiben einige Zeichen im Eingabestrom
zur"uck, mindestens das Zeilenendezeichen ({\tt ASCII.eol}), die beim
n"achsten Lesen zur"uckgeliefert werden. Eine
bessere (weil sicherere) Variante dieser Funktion s"ahe folgendermassen
aus:
\begin{verbatim}
PROCEDURE Ja(text: ARRAY OF CHAR):BOOLEAN;
VAR
  l: INTEGER;
  str: ARRAY[0..3] OF CHAR;
BEGIN
  WriteString(text);
  ReadLn(str,l);
  RETURN CAP(str[0])="J"
END Ja;
\end{verbatim}
\noindent
Diese Funktion liest eine ganze Zeile ein. Der Benutzer kann mit einem
einfachen \keyret{} die Frage verneinen, oder mit \key{j}\keyret{} die
Frage bejahen. Jede Zeichenkette, die mit "`j"' oder "`J"' beginnt
gilt als Zustimmung. "`Jein"' w"urde somit als "`Ja"' interpretiert.
\end{example}

Wurde das Programm von der Workbench aus gestartet, wird ein Konsolenfenster
mit den oben beschriebenen Eigenschaften er"offnet. Die Gr"osse dieses
Fensters ist im Modul {\tt Terminal} vorgegeben. Die Vorgabe ist
\begin{quote} \verb|CON:000/050/640/150| \end{quote}
Es besteht jedoch die M"oglichkeit, Art und Gr"osse des Fensters selbst
zu bestimmen. Vor dem "Offnen des Fensters mit den Vorgabewerten wird
in der Ikone des Programms nach einem ToolTypes-Eintrag
\begin{quote} \verb|WINDOW=| \end{quote}
gesucht. Dieser Eintrag muss ein g"ultiger
Fenstername sein (siehe \cite{AmigaDOS}).
\begin{note}
Der Name des Fensters muss mit angegeben werden! Dies ist
gegen"uber alten Versionen eine Neuerung.%
\footnote{Fr"uher wurde der Name des
eigenen Programms an die Spezifikation angeh"angt.}
Hierdurch ist es aber auch m"oglich, den gew"unschten Screen
unter Kickstart 2.0 in der Fensterbeschreibung mit anzugeben
also beispielsweise
\begin{quote}\tt
WINDOW=CON:0/0/640/150/Prog/AUTO/CLOSE/SCREENPubScr
\end{quote}
\end{note}

\begin{example}
\noindent
Zum Beispiel findet ein Programm "`Demo"' in der Ikone den Eintrag
\begin{verbatim}
  WINDOW=CON:0/0/640/200/Demo-Window
\end{verbatim}
\noindent
dann wird dadurch das Fenster
\begin{verbatim}
  CON:0/0/640/200/Demo-Window
\end{verbatim}
\noindent
ge"offnet.
\end{example}

\begin{note}
F"ur besondere Anwendungen ist es auch m"oglich, andere Ein- und Ausgabekan"ale
zu verwenden. Dabei ist zu beachten, dass Ein- und Ausgabe "uber den gleichen
Kanal abgewickelt werden.
\begin{example}
\begin{verbatim}
   WINDOW=AUX:
   WINDOW=SER:
\end{verbatim}
 usw.
\end{example}
\end{note}

Tritt beim Aufruf von der Workbench beim "Offnen des Terminal-Fen\-sters
ein Fehler auf --- unabh"angig ob es sich um ein anwenderdefiniertes
oder um ein Standard-Fenster handelt ---,
erscheint in einem Requester die Meldung
\begin{quote} \verb|Terminal: Open() -Fehler| \end{quote}
Diese Meldung kann bei einer ung"ultigen Spezifikation des Fensters
oder bei Speichermangel auftreten. Der vom Modul ermittelte Name
wird zus"atzlich angezeigt.

\begin{warning}
Diese Implementation des Moduls Terminal ist f"ur die Verwendung von
Konsolenfenstern und sequentiellen Dateien bei Ein- und Ausgabeumlenkung
konzipiert. Darum ist es m"oglich, dass unter bestimmten Umst"anden
(z.B. RAW: als Ein- Ausgabekanal) nicht alle Funktionen exakt der
Beschreibung folgen.
\end{warning}

\newpage

\section{Windows}

Das Modul {\tt Windows} bietet eine einfache Schnittstelle,
um mit Fenstern zu arbeiten. F"ur die einfache Handhabung
wird keine detaillierte Kenntnis von Intuition gefordert.

{\tt OpenWindow} "offnet ein Fenster mit den angegebenen Koordinaten
{\tt x}, {\tt y}, {\tt w}, {\tt h} --- in Bildpunkten, der Nullpunkt
befindet sich links oben --- und der Kopfzeile {\tt title}. Alle in
Intuition verf"ubaren Standard-Gadgets sowie ein Schiebebalken
auf der rechten Seite k"onnen dem Fenster zugeordnet werden.
So zugewiesene Gadgets m"ussen allerdings vom Benutzer behandelt
werden\footnote{Durch Setzen der entsprechenden IDCMP-Flags
und Behandlung der so eintreffenden Ereignisse}. Ohne spezielle Behandlung
sollten nur das {\tt arranging}- und das {\tt moving}-Gadget
zugewiesen werden, da sie vom System automatisch behandelt werden.

Als Schreibmodus wird {\tt replMd} gesetzt und die Cursorposition ist
{\tt 0}, {\tt 0} (linksoben). Konnte das Fenster nicht ge"offnet
werden, erh"alt {\tt u} den wert {\tt NIL}.

{\tt CloseWindow} schliesst das durch {\tt u} identifizierte Fenster
wieder.

Die Prozedur {\tt GetSize} liefert die Zeilen- und Spaltenzahl des
Fensters {\tt u}.

{\tt XYtoPos} setzt die {\tt x}- und {\tt y}-Koordinate relativ zum
Fensternullpunkt in die Fensterzeile {\tt l} und Spalte {\tt c} um.

Der unsichtbare Cursor kann mit {\tt SetPos} gesetzt werden,
w"ahrend analog {\tt GetPos} die aktuelle Cursorposition liefert.
Die beiden Prozeduren arbeiten mit Zeile und Spalte!

Bei Er"offnen wird die Hinter- und Vordergrundfarbe auf
0 und 1 gesetzt. Mit {\tt SetColor} lassen sich diese Farbwerte
"andern. M"ochten Sie nur einen Wert "andern, k"onnen Sie dem anderen
-1 "ubergeben.

{\tt SetMode} setzt den Schreibmodus f"ur ein bestimmtes Fenster.
Mit {\tt replMd} wird das Buchstabenmuster "uber den momentanen Inhalt
gelegt, {\tt xorMd} "andert die Farbe an den im Muster gesetzten
Stellen und {\tt orMd} setzt die Farbe an den im Muster gesetzten
Stellen. Ist {\tt invMd} gesetzt, wird das Buchstabenmuster
zuerst invertiert, bevor einer der drei beschriebenen Modus zur
Anwendung kommt.

{\tt Scroll} bewegt den Fensterinhalt um soviele Zeilen wie
angegeben, auf"-w"arts bei positiven Gr"ossen und abw"arts bei
negativen {\tt nr}.

Ein Fenster kann durch die Prozedur {\tt Clear} gel"oscht werden.
Das Fenster wird mit der Hintergrundfarbe ausgef"ullt.

{\tt WriteC} schreibt an der aktuellen Cursorposition ein Zeichen
und bewegt den Cursor entsprechend.

{\tt WriteS} schreibt die "ubergebene Zeichenkette an der aktuellen
Cursorposition. Geht die Zeichenkette "uber den rechten
Rand hinaus, wird auf der n"achsten Zeile fortgefahren; ein
anderes Verhalten kann mit {\tt SetClip} erreicht werden.

{\tt WriteL} setzt den Cursor an den Anfang der n"achsten Zeile.

Die Fenster werden normalerweise auf dem Workbench-Bildschirm
er"offnet. Mit {\tt SetScreen} kann jedoch f"ur alle nachfolgenden
Aufrufe der Prozedur {\tt OpenWindow} ein anderer Bildschirm gesetzt werden.
Um wieder zum Work\-bench-Bild\-schirm zur"uckkehren zu k"onnen, muss
{\tt NIL} "ubergeben werden.

Mit der Prozedur {\tt SetClip} k"onnen Sie angegeben,
ob ein zu schreibender Text, der nicht vollst"andig auf der
Fensterzeile Platz hat, abgeschnitten oder auf der n"achsten Zeile
weitergeschrieben werden soll. Wird der Clip-Modus gesetzt
({\tt on} $=$ {\tt TRUE}), bewirkt ausserdem ein Zeilenvorschub am
Ende des Fensters bloss das Setzen des Cursors auf das erste Zeichen
der Zeile.

\begin{note}
Das er"offnete Fenster hat keine IDCMPFlags und somit
auch keinen Reply-Port. Mit der Prozedur
{\tt IntuitionL.ModifyIDCMP} kann dem Fenster ein Port zugewiesen
werden.
\end{note}

