
% 4.11.90/bp
% Fehlt noch: Rawfiles, Beispiele
\section{Der Library-Linker ({\tt M2LibLink\/})}
\label{refLibLink}

Das Betriebssystem des Amigas ist nahezu beliebig erweiterbar.
Die Erweiterungen, um die es an dieser Stelle geht, sind
einander "ahnlich und teilen sich in drei Gruppen:
\begin{description}
\item[Libraries] (sog.\/ "`shared Libraries"', "offentliche Bibliotheken)
sind Sammlungen thematisch zusammengeh"origer
Prozeduren und Funktionen, die von jedem Programm benutzt werden
k"onnen. Der gleiche Code ist dadurch jeweils nur einmal im Speicher
vorhanden und muss nicht in den Programmen enthalten sein. Von Korrekturen,
verbesserten Algorithmen oder erweiterter Hardware profitieren
{\em sofort\/} alle Benutzer ohne Programm-"Anderung.

\item[Devices] dienen der Ein- und Ausgabe. Sie sind Treiber
f"ur physikalische oder virtuelle Ger"ate. Devices k"onnen auch
Library-Prozeduren enthalten.

\item[Resources] stellen Prozeduren zur Verf"ugung, die im Multitasking
eine
einmalig im Rechner vorhandene Hardware verwalten. Sie stellen sicher, dass
jeweils nur {\em ein\/} Prozess Zugriff auf diese Hardware hat.
\end{description}

\medskip
\noindent
Allen drei Gruppen ist gemeinsam, dass die zugeh"origen Dateien keine
normalen Programme sind, sondern einen speziellen Aufbau aufweisen
m"ussen. Sie k"onnen mit dem Linker {\tt m2l} nicht erzeugt werden,
stattdessen m"ussen Sie {\bf M2LibLink} verwenden.

Mit Hilfe des {\bf Library-Linkers} kann man auf relativ einfache
Weise Libraries, Devices und Resources f"ur den Amiga erstellen.
Diese drei Arten werden im folgenden mit dem Oberbegriff
{\bf Objekt} bezeichnet.

Unter Beachtung der vom Linker verlangten Konventionen
schreibt man ein Modul, das aus Definition und Implementation
besteht. Die beiden Quelltexte werden kompiliert und daraufhin
von {\tt M2LibLink} zu dem entsprechenden Objekt
gebunden. Auf Wunsch erzeugt dieser Linker
auch ein Definitionsmodul zur sp"ateren Benutzung in \mtwoamiga{}
oder auch ein sogenanntes FD-File, um das Objekt in fremden
Programmiersprachen benutzen zu k"onnen.

W"ahrend bei einfachen Funktions-Libraries die Kenntnisse
"uber das Betriebssystem des Amigas noch rudiment"ar sein d"urfen,
ist f"ur Resources und besonders f"ur Devices eine sehr gute
Kenntnis des Systems vonn"oten. Derartige Kenntnisse sollen hier
nicht vermittelt werden, sie w"urden den Umfang dieses Handbuches
sprengen.

\subsection{Aufruf und Optionen}

\noindent
Aufruf:

\begin{quote}\tt
M2LibLink \{+-012348acdfimq -l{\cmsltt{}LibFile\/} \\
~~-t{\cmsltt{}TargetFile\/} ? ?? {\cmsltt{}ObjectFile\/}\}
\end{quote}

\begin{example}
\noindent
Ein Beispiel:
\begin{verbatim}
M2LibLink +mf DemoLib
\end{verbatim}
\noindent
Durch diesen Befehl wird die Library {\tt demo.library}, ein Schnittstellenmodul
{\tt txt/Demo.def} und die Beschreibung der Library {\tt demo\_lib.fd}
erzeugt.
\end{example}

Da das Programm {\tt M2LibLink} aus dem herk"ommlichen Linker {\tt m2l}
hervorgegangen ist, verwundert es sicher nicht weiter, dass
Bedienung und Optionen fast identisch sind.

{\tt M2LibLink} besitzt keinen ARexx-Port und keine M"oglichkeit zum
Verzeichniswechsel. Die von {\tt m2l} bekannten M"oglichkeiten zur
Festlegung des Laufzeitsystems ({\tt m} und {\tt r}) sind hier nicht
vorhanden, es wird immer das spezielle, sehr rudiment"are
Laufzeitsystem {\bf LArts.obj} eingebunden. Ebenso ist die
Angabe einer minimalen Stapelgr"osse sinnlos, da die erzeugten
Objekte lediglich Prozeduren enthalten und keine eigenst"andigen
Prozesse sind.

Mit Hilfe der Umgebungsvariablen "`{\tt M2LibLink}"' l"asst sich die
Voreinstellung der Optionen festlegen.

\medskip
\noindent
Die Optionen im einzelnen:

\begin{description}
\item[a] (ask module) Durch die Option "`{\tt +a}"' wird der Library-Linker
veranlasst, vor dem Einlesen jeder Datei dem Benutzer die
M"oglichkeit zu geben, einen anderen Dateinamen einzugeben.
Hierbei zeigt er in eckigen Klammern den Dateinamen an. Wenn
Sie einfach \keyret{} dr"ucken, wird die angezeigte Datei eingelesen,
andernfalls die von Ihnen eingetippte. Dieser Vorgang wird solange
wiederholt, bis die Datei erfolgreich eingelesen werden konnte.
Geben Sie einfach nur ein Minuszeichen ein, wird {\em f"ur diesen
Linkvorgang\/} die Option ausgeschaltet und die restlichen, noch
zu lesenden Dateien ohne Nachfrage geladen.

\item[i] (icon) Falls diese Option eingeschaltet ist, werden f"ur alle erzeugten
Dateien auch Workbench-Ikonen angelegt.
"`{\tt -i}"' unterdr"uckt dies. Wenn der Library-Linker von der Workbench
gestartet wurde, ist die Ikonen-Erzeugung eingeschaltet, beim Start
vom CLI wird standardm"assig keine Ikone erzeugt.
Zur korrekten Funktion m"ussen im Verzeichnis {\tt m2:icons}
die beiden Ikonen {\tt txt.info} und {\tt library.info} vorhanden sein.

\item[c] steht f"ur "`CODE"'. "`{\tt +c}"' bewirkt, dass die einzelnen
CODE-Hunks soweit wie m"oglich in maximal 32kByte grossen Hunks
zusammengelegt werden, was zu einem erheblich k"urzeren Objekt
f"uhren kann. Standardeinstellung f"ur diese Option ist "`{\tt +}"'.

\item[d] steht f"ur "`DATA"'. Nach "`{\tt +d}"' legt der Library-Linker alle
DATA- und BSS-Hunks gleichen Typs (CHIP, FAST, "`normal"') zusammen.
Dies ist auch die Vorgabe. Hierdurch wird
das fertige Objekt etwas kleiner.

\item[l{\cmsltt LibFile}] Hier ist "`{\tt +}"' oder "`{\tt -}"'
ohne Wirkung. Durch diese
Option wird dem Linker mitgeteilt, in welchen Dateien er undefinierte
Symbole suchen soll, die z.B. mit einem Assembler erzeugt und im Modul
als externe Variablen deklariert wurden.
Das Argument {\cmsltt LibFile\/} muss den kompletten Pfad enthalten!
Das "`{\tt l}"' kann sich direkt an die anderen Optionen anschliessen; falls
jedoch mehrere Dateien geladen werden sollen, muss jeweils eine
eigene Option hierf"ur angegeben werden, da alle Zeichen nach dem
"`{\tt l}"' als Teil des Dateinamens eingelesen werden.
Die Angabe einer "`Extra"'-Datei gilt immer nur f"ur das n"achste
zu bearbeitende Objekt. Danach werden diese Angaben vergessen!

\item[t{\cmsltt TargetFile}] bietet die M"oglichkeit, der erzeugten Datei
einen anderen Namen zu geben. Diese Option gilt (wie "`{\tt l}"') nur
f"ur den n"achsten Linkvorgang. Direkt an den Buchstaben "`{\tt t}"' schliesst
sich ein Dateiname (einschliesslich Pfad) an. Standardeinstellung ist der
Modulname des Schnittstellenmoduls mit den Endungen
"`{\tt .library}"', "`{\tt .device}"' oder "`{\tt .resource}"'.

\begin{example}
Beispiel: Ein Device soll gleich im richtigen Verzeichnis abgelegt
werden:
\begin{verbatim}
 M2LibLink -tdevs:myfirst.device MyFirstDev
\end{verbatim}
\end{example}

\item[012348] Auch hierbei sind "`{\tt +}"' oder "`{\tt -}"' wirkungslos.
Durch die Ziffer wird dem Library-Linker mitgeteilt, welche Art
Objektdateien er einbinden soll, um den bestm"oglichen Code f"ur den
Zielprozessor zu erzeugen. Vorgabe ist "`{\tt 0}"'.
\begin{warning}
Da Libraries, Devices und Resources auf jedem Amiga lauf"|f"ahig sein m"ussen,
und das Betriebssystem keine Verwaltung unterschiedlicher Libraries
mit gleichen Namen vorsieht,
sollten diese Optionen m"oglichst {\em nicht\/} benutzt und immer
Code f"ur den MC68000-Prozessor erzeugt werden!
\end{warning}

\item[q] Mit der Option "`{\tt -q}"' werden alle Meldungen des
Library-Linkers unterdr"uckt.
Beim Eintritt in den interaktiven Modus (z.B. durch einen Fehler) wird
die Option wieder auf ihre Standardeinstellung "`{\tt +}"' gesetzt.

\item[m] Durch die Angabe "`{\tt +m}"' wird der Library-Linker veranlasst,
neben dem normalen Link-Vorgang aus dem Definitionsmodul ein
Schnittstellenmodul zu erzeugen.
Nachdem das hierbei erzeugte
Modul compiliert wurde, kann das zugeh"orige Objekt von jedem
mit \mtwoamiga\ erstellten Programm benutzt werden. Diese Option hat
den Standardwert "`{\tt -}"'.

\item[f] Damit auch Programmierer anderer Sprachen in den "`Genuss"'
des Objektes kommen, kann durch die Angabe "`{\tt +f}"' die Erzeugung
einer FD-Datei (function description) veranlasst werden. Dies
ist eine Textdatei, die f"ur jede Prozedur den Namen und die
Parameter-Register angibt.
Diese Option hat den Standardwert "`{\tt -}"'.

\item[??] Die Eingabe zweier Fragezeichen zeigt die Version des Linkers
und den aktuellen Status aller Optionen.
\end{description}


\begin{table}
\begin{center}
\begin{tabular}{|c|c|l|} \hline
Option & Vorgabe & Wirkung \\ \hline \hline
  ? &     & Version und Syntax \\ \hline
  ?? &    & Version, Syntax und Status \\ \hline
  a & -- & Abfrage der Dateinamen \\ \hline
  c & +  & SmallCode \\ \hline
  d & +  & SmallData \\ \hline
  i & WB:+, CLI:-- & Ikonen-Erzeugung \\ \hline
  q & + & Ausgabe von Meldungen \\ \hline
  m & -- & Erzeugung der Schnittstelle\\ \hline
  f & -- & Erzeugung der FD-Datei\\ \hline
  l &    & Lade Extrafiles \\ \hline
  t & Modulname & Name der Zieldatei \\ \hline
 012348 & 0 & Typ der Objektdateien (.ob1 \ldots) \\ \hline
\end{tabular}
\caption{\label{refLibLinkOpts} Optionen des Library-Linkers in Kurzform}
\end{center}
\end{table}



\subsection{Namens-Konventionen}
F"ur ein korrektes Funktionieren des Library-Linkers m"ussen vom Programmierer
bestimmte Konventionen bei der Namensgebung eingehalten werden.

Jedes Objekt besteht aus Definitions- und Implementationsmodul. Der Linker
erzeugt daraus verschiedene andere Dateien. Damit er erkennen
kann, um welche Art Objekt es sich handelt, muss an den Modulnamen jeweils
eine bestimmte Endung angef"ugt werden:

\begin{tabular}{ll}
 Library: & {\bf Lib} \\
 Device: & {\bf Dev} \\
 Resource: & {\bf Rsrc} \\
\end{tabular}

Am einfachsten erkl"aren wir die Namensgebung anhand eines Beispiels.
Es soll eine Library namens "`{\tt MyTest}"' erzeugt werden. Hierzu werden
folgende Dateien ben"otigt bzw.\ erzeugt:

\begin{tabular}{ll}
Definitionsmodul: & {\tt MyTestLib.def} \\
Implementationsmodul: & {\tt MyTestLib.mod} \\
Schnittstellenmodul: & {\tt MyTest.def} \\
FD-Datei: & {\tt MyTest\_lib.fd} \\
Library: & {\tt mytest.library} \\
\end{tabular}

\medskip
\noindent
In das Schnittstellenmodul wird von {\tt M2LibLink}
ausserdem eine Zeichenkettenkonstante
eingef"ugt, die nur aus Kleinbuchstaben besteht. In diesem Beispiel:
\begin{verbatim}
CONST
  myTestName = "mytest.library";
\end{verbatim}

Die in die Library einkodierte Resident-Struktur enth"alt den gleichen
Namen sowie eine Identifikations-Zeichenkette mit folgendem Aufbau:
\begin{quote}
  \tt"\cmsltt Name version.revision \/%
  \tt(\cmsltt Link-Datum\/\tt)",cr,lf,0
\end{quote}
\noindent
In unserem Beispiel:
\begin{quote}\tt
  \dq MyTest 33.10 (4 Nov 1990)",cr,lf,0
\end{quote}

Die Zeichenkette wird immer mit den Zeichen {\tt ASCII.cr},
{\tt ASCII.lf} und dem Nullbyte abgeschlossen.

In der FD-Datei erscheint im Beispiel "`{\tt \_MyTestBase}"' als Name
der Library-Basis.

\begin{note}
Der Modulname des Schnittstellenmoduls ist immer der Name des Moduls
ohne die spezielle Endung. Man sollte darauf achten, dass kein
Modul doppelt vorhanden ist. Falls man etwa auf die Idee kommt, auch
ein Device namens "`{\tt MyTest}"' zu erstellen, ist die Schnittstelle
{\tt MyTest.def} zweimal vorhanden, bzw.\ die alte wird gel"oscht.
\end{note}


\subsection{Sonstige Konventionen}

F"ur die Erstellung des Resident-Headers%
\footnote{eine spezielle, im Objekt vorhandene Struktur}
ben"otigt der Library-Linker neben den bereits
bekannten Namen noch zus"atzliche Informationen. Dies sind die Version
und die Revision des Moduls sowie die Gr"osse der zugeh"origen Library-Struktur.
Alle drei m"ussen als ganzzahlige Konstanten definiert werden. Dabei
geh"oren {\bf version} und {\bf baseSize} sinnvollerweise ins
Definitionsmodul und {\bf revision} in die Implementation.

Die Version sollte jeweils den unterliegenden Amiga-Bibliotheken
entsprechen, d.h., f"ur Kickstart 1.2 sollte die Version 33,
f"ur Kickstart 1.3 die Version 34 und f"ur Kickstart 2.0 Version 37
verwendet werden.

Die eigene Library-Struktur muss immer als {\tt RECORD} deklariert werden
und als erstes Element eine Library-Struktur des Moduls {\tt ExecD}
enthalten. Daran k"onnen sich beliebige eigene globale Variablen
anschliessen. {\em Alle\/} globalen Variablen sollten innerhalb
dieser Struktur angelegt werden.

Werden die verlangten Konstanten nicht wie verlangt deklariert,
bricht der Linker mit einer Fehlermeldung ab.

\begin{note}
Der Library-Linker ben"otigt zum Arbeiten unbedingt die zugeh"orige
Referenz-Datei. Diese wird vom Compiler erzeugt, wenn die Option
"`{\tt d}"' gesetzt ist (Normalfall). In diesem Fall wird aber der erzeugte
Code nicht optimiert. Speziell f"ur den Library-Linker bietet der Compiler
die Option "`{\tt +@}"', die bewirkt, dass sowohl der Code optimiert, als
auch eine Referenz-Datei erzeugt wird. Eine dadurch erzeugte
Referenz-Datei ist aber {\em f"ur den Debugger\/} ung"ultig, weil die
darin enthaltenen Relationen zwischen Programmz"ahler und Quelltext-Position
nicht korrekt sind!
\end{note}

\begin{example}
\begin{verbatim}
DEFINITION MODULE MyTestLib;

FROM ExecD IMPORT Library,List;

TYPE
  MyTestBasePtr = POINTER TO MyTestBase;
  MyTestBase = RECORD
    lib:Library; (* Pflicht! *)
    users:List (* z.B.: Liste der Benutzer *)
    ...
  END;

CONST
  version = 33; (* Pflicht! *)
  baseSize = SIZE(MyTestBase); (* Pflicht! *)
...
...
IMPLEMENTATION MODULE MyTestLib;
...
CONST
  revision = 10; (* Pflicht! *)
...
\end{verbatim}
\end{example}


\subsection{Pflichtprozeduren}
Das Betriebssystem schreibt f"ur jedes Objekt bestimmte Prozeduren vor,
die immer vorhanden sein m"ussen. Diese sogenannten Pflichtprozeduren m"ussen
innerhalb des Definitionsmoduls als {\em erste\/} und
genau in der angegebenen Reihenfolge deklariert werden. Die {\em Namen\/}
der Prozeduren sind zwar nicht vorgeschrieben, wir empfehlen
aber die folgenden Namen, um Kollisionen zu vermeiden.

Alle Prozeduren erhalten im Register A6 einen Zeiger auf die Basis der
eigenen Library (Device, Resource). Die Open- und Close-Prozeduren
des Moduls
--- und nur diese --- werden vom Betriebssystem Exec
im Forbid-Status aufgerufen.

\subsubsection{Libraries}
F"ur Libraries sind die folgenden vier Prozeduren vorgeschrieben:
\begin{ttscript}{LibExpunge}
\item[LibOpen] wird beim "Offnen der Library aufgerufen. Hier sollte
mindestens der in der Library-Struktur enthaltene "Offnungs-Z"ahler erh"oht
und das Expunge-Flag gel"oscht werden. Weitergehende Operationen sind
m"oglich, aber nur bei einigen Libraries notwendig. Nach korrekter
Ausf"uhrung wird im Register D0 die Basis der eigenen Library zur"uckgegeben,
im Fehlerfall ent"-h"alt D0 den Wert 0 ({\tt NIL}).
\item[LibClose] wird beim Schliessen der Library aufgerufen. Sie muss
mindestens den "Offnungsz"ahler erniedrigen und danach testen, ob er 0
ist, d.h.\ kein Prozess die Library ge"offnet hat. In diesem Fall
muss bei gesetztem Expunge-Flag die nachfolgend beschriebene
Prozedur {\tt LibExpunge}
aufgerufen und deren Resultat zur"uckgegeben werden. In allen
anderen F"allen gibt man 0 zur"uck.
\item[LibExpunge] wird vom Betriebssystem aufgerufen, wenn die Library
komplett aus dem System entfernt werden soll, um Speicher frei zu machen.
Falls der "Offnungsz"ahler nicht 0 ist, wird von
dieser Prozedur das Expunge-Flag gesetzt und 0 zur"uckgegeben,
andernfalls wird aufger"aumt und die Library aus dem System entfernt.
Hierzu wird zun"achst die Basis aus der Library-Liste des Betriebssystems
entfernt, dann die Prozedur {\tt Arts.Terminate} aufgerufen,
welche die {\tt CLOSE}-Teile der Moduln
aufruft und somit auch alle ge"offneten
Libraries schliesst. Daraufhin wird der von der Library-Struktur belegte
Speicher einschliesslich der Sprungliste freigegeben
--- zu beachten ist, dass die Exec-Library
nun bereits geschlossen ist --- und der Inhalt der Variablen
{\tt Arts.dosCmdBuf} im Register D0 zur"uckgeliefert. Diese Variable
enth"alt die sogenannte SegList der Library. Danach kann auch diese SegList
vom Betriebssystem wieder freigegeben werden.

\item[LibExtFunc] erf"ullt keine Funktion. Sie ist f"ur Erweiterungen
der Amiga-Entwickler vorgesehen und muss gegenw"artig immer 0 zur"uckgeben.
\end{ttscript}

\subsubsection{Devices}
Die Programmierung von (korrekten!) Devices z"ahlt sicher zu den schwierigsten
Aufgaben eines Amiga-Programmierers.

 Die M"oglichkeiten, ein Device
aufzubauen sind vielf"altig, es k"onnen beliebig viele Units
verwaltet, eigene Prozesse gestartet werden, und "ahnliches. Jedes Device muss
eine {\tt IORequest}-Struktur definieren,
sowie eine Anzahl von Pflicht-Kommandos
und unter Umst"anden auch selbstdefinierte bearbeiten k"onnen.

Wir stellen hier nur die sechs Pflichtprozeduren in Kurzform vor,
f"ur weitergehende Informationen ziehen Sie bitte die umfangreiche
Fachliteratur zu Rate!

\begin{ttscript}{Devexpunge}

\item[DevOpen] erh"alt im Register A1 einen Zeiger auf den zugeh"origen
IORequest, in D0 die Nummer der Unit und in D1 die Flags. Hier muss
"ahnlich wie bei Libraries verfahren werden, jedoch sind noch weitergehende
Operationen erforderlich. Die R"uckgabe des Resultates erfolgt hierbei indirekt
"uber den IORequest.

\item[DevClose] erh"alt in A1 einen Zeiger auf den zugeh"origen IORequest.
Sie muss die zugeh"orige Unit schliessen und danach so verfahren
wie {\tt LibClose}, also unter Umst"anden auch die Prozedur
{\tt DevExpunge} aufrufen.
R"uckgabewert ist also ebenfalls 0 (NIL) oder die zugeh"orige SegList.

\item[DevExpunge] ist identisch mit {\tt LibExpunge}. Bei Devices sind aber
meist noch mehr "`Aufr"aumarbeiten"' erforderlich.

\item[DevExtFunc] ist f"ur Erweiterungen reserviert und muss immer
0 zur"uckgeben.

\item[DevBeginIO] startet eine Ein- oder Ausgabe, die durch einen
{\tt IORequest} beschrieben ist, auf den Register A1 zeigt.

\item[DevAbortIO] bricht eine Ein- oder Ausgabe ab. Register A1
zeigt auf den zugeh"origen {\tt IORequest}.

\end{ttscript}

\subsubsection{Resources}
Der Bedarf selbstbeschriebener Resources d"urfte gering sein,
da hierzu immer auch eine Hardware-Entwicklung geh"ort. F"ur
Resources sind keine Pflichtprozeduren vorgeschrieben, woraus folgt,
dass eine Resource nicht wieder aus dem System entfernt werden kann.
Andererseits wird eine Resource erst dann unn"otig, wenn auch die
von ihr verwaltete Hardware entfernt wird. Trotzdem steht es
dem Programmierer nat"urlich frei, eine entsprechende Expunge-Prozedur zu
implementieren.


\subsection{Das Schnittstellen-Modul}
Der Library-Linker erzeugt nach der Option "`{\tt +m}"' automatisch
aus dem Definitionsmodul ein Schnittstellen-Modul. Der Name
des erzeugten Moduls ist der Modulname ohne die spezielle Endung.
Aus "`{\tt MyTestLib}"' wird also "`{\tt MyTest}"', die Datei wird als
{\tt txt/MyTest.def} angelegt.

\medskip
\noindent
{\tt M2LibLink} geht hierbei wie folgt vor:
\begin{enumerate}
\item F"ur Libraries wird ein Library-Kopf erzeugt, z.B.
\begin{quote} \verb|DEFINITION MODULE MyTest{"mytest.library",33};|\end{quote}
F"ur Devices und Resources erstellt der Library-Linker ein implementationsloses
Modul, z.B.
\begin{verbatim}
      (*$ Implementation:=FALSE *)
      DEFINITION MODULE MyTest;
\end{verbatim}

\item Es wird die Deklaration einer Zeichenkettenkonstanten eingef"ugt,
die den Namen des Objektes angibt.

\item Die Definitionen der Pflichtprozeduren werden gel"oscht.

\item An alle anderen Prozeduren wird eine CODE-Anweisung angef"ugt.
  Die Offsets vermindern sich dabei fortlaufend um 6, deshalb ist es
  sehr wichtig, dass die Pflichtprozeduren ganz am Anfang und in
  der richtigen Reihenfolge stehen.

\item Der Modulname am Schluss wird ge"andert.
\end{enumerate}

Nach dieser automatischen Bearbeitung sollte das Schnittstellen-Modul
sofort "ubersetzbar sein. Es kann jedoch zun"achst nachbearbeitet
werden, um z.B. nicht-"offentliche Deklarationen zu l"oschen,
die Prozeduren alphabetisch zu sortieren oder den in Abschnitt
\ref{refpp} beschriebenen "`Trick"' mit den Register-Parametern
anzuwenden.

\subsection{Das Laufzeitsystem LArts}
\label{LArts}
{\tt M2LibLink} sucht im Pfad f"ur das Modul {\tt Arts} die Datei
"`{\tt LArts.obj}"'.
Dies ist eine spezielle Version von {\tt Arts}, die auf das absolut Notwendige
"`abgespeckt"' wurde und somit recht kurz ist.

\subsubsection{Arts-Variablen}
Von den Variablen des Moduls {\tt Arts} sind lediglich zwei von Bedeutung,
alle anderen sind unbenutzt.

\begin{ttscript}{dosCmdBuf}
\item[dosCmdBuf] enth"alt die SegList, die bei der Initialisierung vom
Betriebssystem "ubergeben wurde. Sie wird nur von der Expunge-Prozedur
ben"otigt.

\item[dosCmdLen] ist ein Flag f"ur die Initialisierungsphase. Sie enth"alt
den Zeiger
auf die Library und wird von {\tt Arts.Startup} an Dos/Exec zur"uckgegeben.
Falls w"ahrend der Initialisierung ein Fehler auftritt, m"ussen alle bis
dahin allozierten Dinge wieder freigegeben und {\tt dosCmdLen} auf Null gesetzt
werden. Die CLOSE-Teile aller beteiligten Module werden dann auf
jeden Fall auch aufgerufen! Diese sind {\em sehr sorgf"altig und sicher\/}
zu programmieren!
\end{ttscript}


\subsubsection{Arts-Prozeduren}

{\tt Startup} wird beim Laden des Objekts automatisch aufgerufen.
Diese Prozedur l"adt das Register A4 mit der Basis der globalen
\near-Variablen, legt die "ubergebene SegList in die Variable
{\tt dosCmdBuf} und die
Library-Basis in {\tt dosCmdLen} ab. Danach werden die Hauptprozeduren der
Module aufgerufen, also hier auch die importierten Libraries ge"offnet.

{\tt Terminate} ruft die CLOSE-Prozeduren auf und schliesst somit auch die
benutzten Libraries. Diese Routine darf {\em nur} von der Expunge-Prozedur
aufgerufen werden.

{\tt Requester} liefert immer {\tt FALSE} zur"uck.
{\tt BreakPoint} und {\tt StkChk} kehren einfach zum Aufrufer zur"uck.
{\tt SystemError}, {\tt Exit} und {\tt Error} f"uhren zum Guru.
{\tt Assert} f"uhrt nur bei nicht zutreffender Bedingung zum Guru,
kehrt ansonsten einfach zur"uck.

\begin{note} "`Guru"' bedeutet in der gegenw"artigen Implementation:
{\tt ASSEMBLE(ILLEGAL END)}.
Der daraus resultierende "`Guru"' wird von einem M2Amiga-Programm
selbstverst"andlich abgefangen!
Man sollte also unbedingt sehr "`sauber"' programmieren, da jeder
Laufzeitfehler zu einem Guru f"uhrt. Nach dem ausf"uhrlichen Testen
sollten alle Laufzeit-Tests abgeschaltet werden.
\end{note}

{\tt Mulu32}, {\tt Muls32}, {\tt Divu32}, {\tt Divs32} und {\tt CloseLib}
sind normal implementiert. {\tt OpenLib} setzt im Fehlerfall {\tt dosCmdLen}
auf 0.

\subsubsection{Die Modul-R\protect"umpfe}
Der Hauptteil jedes Moduls wird von der Prozedur {\tt Arts.Startup} aufgerufen.
Dieser Aufruf geschieht im Forbid-Zustand, d.h.\ ein Taskwechsel
ist hier unterbunden. Folglich haben die Prozeduren "`sicheren"'
Zugriff auf alle globalen Variablen. An dieser Stelle sollten die
notwendigen Initialisierungen durchgef"uhrt werden. Zum Beispiel
kann man hier zum sp"ateren, leichteren Zugriff auf die Basis
einen Zeiger darauf in einer globalen Variablen ablegen. Dadurch hat
man die Wahl, innerhalb der exportierten Prozeduren entweder das Register
A6 oder diese globale Variable als Basis zu benutzen.

Falls in einer der Initialisierungs-Prozeduren ein Fehler auftritt,
sollte diese Prozedur die Variable {\tt dosCmdLen} auf 0 setzen.
{\tt Startup} pr"uft nach der Initialisierungsphase diese Variable und
verzweigt im Fehlerfall direkt nach {\tt Terminate}. Dadurch werden alle
ben"otigten Objekte auch im Fehlerfall wieder sauber freigegeben.

Damit im eingetretenen Fehlerfall keine weiteren Initialisierungen
erfolgen, sollte jeder Modulrumpf und jede {\tt CLOSE}-Prozedur
etwa so aussehen:
\begin{verbatim}
BEGIN
  IF dosCmdLen<>0 THEN
    ...
  END
END.
\end{verbatim}

\subsection{Hinweise zur Programmierung}

\subsubsection{Roh-Dateien}
Als Service bieten wir dem Programmierer einige "`rohe"' Moduln,
die als Ausgangspunkt einer Entwicklung dienen k"onnen.
F"ur Libraries, Devices und Resources gibt es je ein Definitions-
und ein Implementationsmodul. Die Dateien heissen:

\begin{itemize}
\item
  {\tt SampleLib.rawdef} und {\tt SampleLib.rawmod} 
\item
  {\tt SampleDev.rawdef} und {\tt SampleDev.rawmod}
\item
  {\tt SampleRsrc.rawdef} und {\tt SampleRsrc.rawmod}
\end{itemize}

\medskip
\noindent
Bei der Bearbeitung muss zun"achst die Datei auf eine neue umkopiert werden,
da man die Originale nat"urlich nicht zerst"oren sollte. Daraufhin
muss jeweils das Zeichen "`\S' durch den Modulnamen ersetzt werden.
Danach hat man bereits einen guten Ausgangspunkt und kann die
eigenen Deklarationen an den bezeichneten Stellen einf"ugen. Die
Implementation der Pflichtprozeduren ist zumindest f"ur Libraries
bereits durchgef"uhrt und muss nur in besonderen F"allen erweitert werden.
Bitte lesen Sie unbedingt die Kommentare!

Einige kleine Beispiele f"ur Libraries und eine Resource finden
Sie auf der Diskette. Die "`{\tt HardClock.resource}"' ist allerdings
mittlerweile von der Betriebssystem Version 2.0 "uberholt
worden und sollte {\em nicht\/} benutzt werden!

\subsubsection{Importe}
Ein Objekt kann aus beliebig vielen Modulen bestehen, jedoch m"ussen
alle Moduln auch daf"ur geeignet sein, insbesondere reentrant.
Von den zum M2Amiga-System geh"orenden Bibliotheksmodulen sollten
nur die Libraries und implementationslose Module importiert
werden. Insbesondere  sollte man nicht solche Moduln wie Terminal, Heap,
FileSystem oder "ahnliche importieren, da diese nicht reentrant sind
und zum Teil auch auf der Prozess-Struktur oder bestimmten --- hier
ung"ultigen --- Variablen des Moduls Arts operieren!

\subsubsection{Register-Konvention}
Jede Library-Prozedur muss sich an die Register-Konventionen des Amigas
halten. Die Register D2\ldots D7, A2\ldots A7 und FP2\ldots FP7 d"urfen
nicht ver"andert werden. Dies ist im Normalfall durch den Compiler
gew"ahrleistet. Vollst"andig in Assembler implementierte Prozeduren m"ussen
die benutzten Register jedoch selbst retten und wiederherstellen.

\subsubsection{Register A4}
Das Register A4 ist der Zeiger auf die globalen \near-Variablen. Es
wird in einem normalen \mtwo-Programm nur einmal geladen und danach
nicht mehr ver"andert. Eine Library hingegen stellt fremden Prozessen
Prozeduren zur Verf"ugung. Bei Eintritt in diese Prozeduren ist das Register
A4 deshalb zu retten und korrekt zu initialisieren. Dies wird mit der
Compiler-Anweisung
\begin{quote}\verb|(*$ LoadA4:=TRUE *)|\end{quote}
erreicht. {\em Jede} exportierte Prozedur muss deshalb vor ihrem
{\tt BEGIN} diese Anweisung enthalten!

\begin{warning}
Nicht nur der Zugriff auf die globalen Variablen, sondern auch Aufrufe
an die importierten Libraries setzen ein korrekt initialisiertes
Register A4 voraus! Dies wird allzu leicht vergessen und f"uhrt zum Guru!
\end{warning}

\subsubsection{Reentrant}
Da eine Library (Device, Resource) sinnvollerweise von mehreren
Programmen gleichzeitig benutzt wird, m"ussen alle exportierten
Prozeduren wiedereintrittsf"ahig (reentrant) sein.
Ein schreibender Zugriff auf globale Variablen muss deshalb
durch Semaphoren oder eine {\tt Forbid}-{\tt Permit}
Klammerung gesichert sein!
Die {\tt Open}-, {\tt Close}- und {\tt Expunge}-Prozeduren
sowie die Hauptprozedur
des Moduls werden vom Betriebssystem bereits im Forbid-Status
aufgerufen.

Man sollte die Anzahl globaler Variablen m"oglichst gering halten und die
zur Verwaltung notwendigen in den Basis-{\tt RECORD} legen.

Selbstmodifizierender Code ist selbstverst"andlich absolut verboten!

\subsubsection{Versions-Kontrolle}
W"ahrend in \mtwo{} die Schl"ussel importierter Module immer auf
{\em exakte\/} Gleichheit "uberpr"uft werden und somit hieraus resultierende
Laufzeitfehler unm"oglich sind, kennt das Betriebssystem des Amigas
f"ur Libraries nur eine {\em Mindest-Version}. Daraus folgt, dass
die Definition eines Objektes niemals ver"andert werden darf, sobald sie
ver"offentlicht wurde. Insbesondere die Reihenfolge und die Parameter
der Prozeduren m"ussen f"ur immer erhalten bleiben! Es d"urfen nur
Erweiterungen am Ende vorgenommen und veraltete Prozeduren als solche
kommentiert --- aber {\em nicht auskommentiert!\/} --- werden,
wie dies beispielsweise bei
der Funktion {\tt ExecL.OldOpenLibrary} geschah.

Noch wichtiger ist dies bei Devices und Resources. Hier gibt es "uberhaupt
keine Versionskontrolle, deshalb sind nicht einmal Erweiterungen
m"oglich, allenfalls bei der Anzahl der Device-Kommandos.

Man sollte folglich vor einer Ver"offentlichung sehr lange und ausf"uhrlich
nicht nur die Implementation, sondern auch die Definition testen und
"uberdenken.

\subsubsection{Prozedur-Parameter}
\label{refpp}
Nach der Amiga-Konvention ist es "ublich, Parameter in den Registern zu
"ubergeben. Dabei sollen alle Zeiger und Adressen ab A0 und die Werte ab
D0 angegeben werden. Nun h"alt sich nicht einmal die {\tt exec.library} daran,
vom Dos ganz zu schweigen.

Wenn die Prozeduren von allen Programmierern aller Sprachen benutzbar
sein sollen, ist es unumg"anglich, die Parameter in Registern zu "ubergeben.
Hier ergeben sich allerdings unter M2Amiga einige Probleme: alle als
Parameter belegten Register sind innerhalb der Prozedur {\em markiert\/},
also gesperrt und vom Compiler nicht f"ur Berechnungen nutzbar.
Weiterhin gibt es h"aufig Probleme, wenn man D0 und D1 mit Parametern
belegt, man sollte also jeweils mit D2 beginnen oder den folgenden
Vorschlag in Betracht ziehen:

Die Parameter werden {\em nur im Schnittstellenmodul\/} als solche angegeben.
Im Definitions- und Implementationsmodul hingegen werden sie nicht
angegeben und die zugeh"origen Registerinhalte gleich bei Eintritt in
die Prozedur in lokalen Variablen abgelegt (mit {\tt SYSTEM.REG} oder
{\tt ASSEMBLE}). Diese Vorgehensweise erfordet allerdings sehr viel Umsicht
vom Programmierer.

Bei einer gr"osseren Zahl Parameter werden somit die freien Register immer
weniger, was den Compiler in arge Schwierigkeiten bringt. In diesem Fall
sollte man sich derart behelfen,
dass man mehrere Parameter in einem {\tt RECORD}
zusammenfasst und nur einen Zeiger darauf "ubergibt, wie z.B. bei
{\tt IntuitionD.OpenScreen}.

Die "Ubergabe von Zeichenketten und offenen Feldern allgemein ist mit Hilfe von
Registern nat"urlich nicht m"oglich, man muss die Adresse und die L"ange
({\tt HIGH}-Wert) getrennt in zwei Registern angeben.

Ganz anders liegt der Fall, wenn die Prozeduren nur f"ur den "`erlauchten"'
Kreis der \mtwoamiga-Programmierer geplant sind. Es spricht nichts dagegen,
Parameter ganz normal auf dem Stack zu "ubergeben, was im allgemeinen Code
und Zeit sowohl in der Library als auch im aufrufenden Programm spart.
Ausserdem k"onnen in diesem Fall auch Zeichenketten
und offene Felder ganz normal
benutzt werden. In der erzeugten FD-Datei erscheint in diesem Fall
allerdings "`{\tt ??}"'\ anstelle des Registers. Da die Prozeduren ohnehin
nur von M2Amiga benutzbar sind, ist eine FD-Datei aber unn"otig.

\begin{warning}
Die exportierten Library-Prozeduren d"urfen {\em auf keinen Fall\/} das
Register A6 als Parameter benutzen, sonst sind Abst"urze vorprogrammiert!
Devices und Resources hingegen {\em m"ussen} (zumindest im
Schnittstellen-Modul) f"ur ihre exportierten Prozeduren das Register
A6 mit der eigenen Basis belegen.
\end{warning}

\subsubsection{Der Typ {\tt BOOLEAN}}

Das Thema "`{\tt BOOLEAN}"' wird nur dann aktuell, wenn die Libraries von
anderen Programmiersprachen benutzt werden sollen. In \mtwoamiga{} ist
der Typ {\tt BOOLEAN} nur ein Byte gross,
in anderen Sprachen manchmal zwei oder vier
Byte. {\tt TRUE} ist alles, was ungleich Null ist,
\mtwoamiga{} setzt und pr"uft
nur das niederwertigste Byte. Funktionsr"uckgaben werden allerdings immer
auf Langworte erweitert.

\subsubsection{Testen}

Selbstverst"andlich sollten nur sehr gut ausgetestete Prozeduren in eine
Library aufgenommen werden. Zum Testen von Libraries kann man zun"achst
einfach aus dem Definitionsmodul importieren, w"ahrend im
Implementationsmodul noch alle Laufzeittests aktiviert sind.
Sp"ater schaltet man dann
alle Tests ab, generiert die Library und importiert aus dem Interfacemodul.
Dies geht allerdings nur, wenn die Open- und Close-Prozeduren keine
speziellen Aktionen vornehmen.

Das Testen von Devices und Resources gestaltet sich dagegegen sehr
schwierig, da sie stark von Exec abh"angen und jeder Laufzeitfehler
sofort zum Guru f"uhrt. Ein Debugger hilft hier auch kaum weiter,
nur sehr sauberes Programmieren.

