Nächste Seite: Optionen der Kommandozeile Aufwärts: Der Compiler Vorherige Seite: Compiler-Ausgaben im Quelltext

## Bedeutung der Optionen

Jede Option wird im folgenden in der Form

Bedeutung
Name | interaktiv | Typ | Vorgabe

dargestellt. Hierbei bezeichnet

Name
  den Namen der Option, mit dem sie im Quelltext ansprechbar ist.
interaktiv
  ist der Buchstabe, der die Option von der Kommandozeile (oder interaktiv) beeinflusst. Nicht alle Optionen sind von der Kommandozeile beeinflussbar. Für sie erscheint die Zeichenkette ,,n.a.`` (nicht anwendbar).
Typ
  bezeichnet den Typ und Änderungsbereich der Option, d.h. ob sie stapelbar oder bereichsbezogen ist.
Vorgabe
  gibt den Vorgabewert (Default) der Option an:
  - ,,TRUE`` = ,,`+``` = eingeschaltet,
  - ,,FALSE`` = ,,`-``` = ausgeschaltet.

Es folgt nun eine genaue Beschreibung der Optionen im einzelnen:

Stapelkontrolle
StackChk | s | stapelbar | TRUE

Das Betriebssystem kontrolliert nicht, ob ein Prozess den ihm zugewiesenen Stapelbereich überschreitet. Ist dies der Fall, stellt sich meist ein unerklärlicher Laufzeitfehler ein, dessen Ursache kaum feststellbar ist. Der Compiler generiert Code zur Überprüfung des Stackbereichs. Diese Überprüfung muss zu Beginn jeder Prozedur, sowie manchmal auch innerhalb der Prozedur durchgeführt werden. Dies vergrössert den Code und verlangsamt das Programm. Werden keine Prozeduren rekursiv aufgerufen, und ist sonst ein Stacküberlauf unwahrscheinlich, kann die Option ausgeschaltet werden.

Die Option wird zu Beginn jeder Prozedur eingefroren und am Ende wieder freigegeben. Der Änderbarkeitsbereich ist identisch mit dem der bereichsbezogenen Optionen.

Bereichskontrolle
RangeChk | r | stapelbar | TRUE

Wird auf einen Unterbereich (``subrange`` wie `[0..31]` oder ein Feld wie `a[3]`) zugegriffen, generiert der Compiler Code, um die Einhaltung der Bereichsgrenzen zu überprüfen. Unter- oder Überschreiten eines solchen Bereichs bricht das Programm mit einem Laufzeitfehler ab. Ist das Programm vorsichtig ausgetestet (und nur dann), kann die Kontrolle mit `(*$ RangeChk:=FALSE *)` ausgeschaltet werden, um etwas Geschwindigkeit zu gewinnen.

Aber auch während der Compilation hat diese Option eine Wirkung. Der Compiler kann konstante Werte bereits zu dieser Zeit auf die Einhaltung von Bereichsgrenzen überprüfen.

Über-, Unterlaufskontrolle
OverflowChk | v | stapelbar | TRUE

Die interne Zahlenrepräsentation kennt keine zu grossen oder zu kleinen Zahlen. Jede Über- oder Unterschreitung bei der Berechnung von Ausdrücken lässt sich jedoch durch das Testen eines speziellen Prozessor-Registers (CCR, ``condition code register``) feststellen. Der Compiler generiert Überprüfungscode, der im Fehlerfall zur Laufzeit das Programm abbricht. Ist das Programm vorsichtig ausgetestet, kann diese Kontrolle durch

> `(*$ OverflowChk:=FALSE *)`

ausgeschaltet werden.

Zeigerkontrolle
NilChk | n | stapelbar | TRUE

Die Verwendung nicht-initialisierter Zeiger kann bei ihrer Dereferenzierung zu unvorhersehbaren Ergebnissen und Programm-Abstürzen führen. Der Compiler erzeugt Code, der zur Laufzeit testet, ob ein Zeiger auf die Adresse 0 (`NIL`) verweist. Dadurch kann zur Laufzeit das Programm abgebrochen werden. Ist das Programm vorsichtig ausgetestet, kann diese Überprüfung durch

> `(*$ NilChk:=FALSE *)`

ausgeschaltet werden.

Nullinitialisierung
EntryClear | e | stapelbar | TRUE

Da der Anfangswert einer lokalen Variablen nicht bestimmt ist, werden diese explizit auf Null gesetzt. Somit kann die Zeigerkontrolle richtig gut greifen. Soll diese Operation nicht durchgeführt werden, muss die Option mit

> `(*$ EntryClear:=FALSE *)`

ausgeschaltet werden.

Fallüberprüfung
CaseChk | c | stapelbar | TRUE

Wenn innerhalb einer `CASE`-Anweisung der aktuelle Wert ausserhalb aller angegebenen Teilbereiche liegt und kein `ELSE`-Teil angegeben wurde, wird das Programm mit einem Laufzeitfehler abgebrochen. Für diese Überprüfung wird dazu vom Compiler Code generiert, der durch die Option

> `(*$ CaseChk:=FALSE *)`

vermieden wird. Die Wirkung ist identisch mit der Angabe eines leeren `ELSE`-Teiles.

Funktionsrückgabe
ReturnChk | f | stapelbar | TRUE

Am Ende jeder Funktionsprozedur generiert der Compiler Code, der im Falle einer fehlenden `RETURN`-Anweisung ausgeführt wird und das Programm mit einem Laufzeitfehler abbricht. Ist bei einer Funktionsprozedur die ordnungsgemässe Beendigung garantiert (und nur dann), kann die Generierung des Überprüfungscodes mit

> `(*$ ReturnChk:=FALSE *)`

abgeschaltet werden.

Ein-/Ausgangs-Code
EntryExitCode | n.a. | bereichsbezogen | TRUE

Jede Prozedur führt zu Beginn einen speziellen Code aus, der eine Stapelüberprüfung vornimmt, Platz für die lokalen Variablen auf dem Stapel alloziert, den dynamischen Link erstellt, die innerhalb der Prozedur benutzten Register auf dem Stack ablegt, und bei Bedarf die offenen Feldparameter auf den Stack kopiert. Am Ende der Prozedur werden (bei Funktionsprozeduren) der Code zur Rückgabekontrolle generiert, die zu Beginn geretteten Register vom Stapel geholt, die lokalen Variablen und die Parameter abgebaut und eine Rückkehranweisung ausgeführt.

Diese beiden Codeteile werden nach

> `(*$ EntryExitCode:=FALSE *)`

nicht erzeugt. Dies wird vor allem bei reinen Assembler-Prozeduren, bei denen der Programmierer für alle oben genannten Aktionen selbst verantwortlich ist, oder bei Prozeduren, die lediglich als ,,Verpackung`` für Daten dienen, benötigt.

Offene Felder
CopyDyn | n.a. | bereichsbezogen | TRUE

Eine Prozedur, die offene Feldparameter als Werteparameter besitzt, muss diese zu Beginn auf den Stack kopieren, damit die übergebene Variable oder Konstante nicht verändert werden kann (siehe auch 5.5.5, Seite ). Für die Herstellung der Kopie muss Code erzeugt werden. Falls der Parameter innerhalb der Prozedur nicht verändert wird, kann das Kopieren mit der Option

> `(*$ CopyDyn:=FALSE *)`

unterbunden werden, was Code und Laufzeit spart. Danach wird der Parameter wie ein VAR-Parameter behandelt, behält aber den Vorteil, dass auch Konstanten übergeben werden können.

Parameter-Abbau
ParDealloc | n.a. | bereichsbezogen | TRUE

In dealloziert jede Prozedur ihre Parameter selbst wieder, da sie aus der Vereinbarung genau weiss, mit wievielen Parametern sie aufgerufen wurde. In der Sprache C werden die Parameter vom Aufrufer dealloziert, da nur dieser weiss, wieviele Parameter er übergeben hat. Einige Betriebssystem-Prozeduren benötigen eine Prozedur als Parameter. Diese dürfen ihre Parameter dann allerdings nicht selbst abbauen, da dies ja die aufrufende Prozedur des Betriebssystems tut. Der Parameter-Abbau kann mit

> `(*$ ParDealloc:=FALSE*)`

unterbunden werden.

Sichere und lade A4
LoadA4 | n.a. | bereichsbezogen | FALSE

Normalerweise wird das Register A4 von unserem -Laufzeitsystem zu Beginn des Programmes einmal mit der Basis der globalen -Variablen initialisiert und während des Programmlaufs nicht verändert. Falls jedoch -Prozeduren vom Betriebssystem aufgerufen werden, z.B. Interrupt-Handler, ist A4 zu Beginn der Prozedur ,,zerstört`` und muss neu ,,beschafft`` werden. Näheres steht in 6.2.2, Seite . Dort befindet sich auch ein ausführliches Beispiel für den Nutzen dieser Option. Die Angabe

> `(*$ LoadA4:=TRUE *)`

gilt für die nächste Prozedur und bewirkt, dass Register A4 mit den anderen Registern auf den Stack gerettet und mit der Basis der -Variablen (,,`_LinkerDB```) geladen wird. Am Ende der Prozedur wird A4 wiederhergestellt. Damit ist ein Programm nicht mehr residentfähig, da jeder Aufruf eines residentfähigen Programms seine eigenen globalen Daten bekommt. Sie in diesem Fall die folgende Option!

Sichere A4
SaveA4 | n.a. | bereichsbezogen | FALSE

Diese Option ist fast identisch mit LoadA4. Die Angabe

> `(*$ SaveA4:=TRUE *)`

gilt für die nächste Prozedur und bewirkt, dass das Register A4 mit den anderen Registern auf den Stack gerettet und am Prozedurende wiederhergestellt wird. Hier wird also - im Gegensatz zu LoadA4 -- das Register nicht explizit mit einem Wert geladen, sondern nur gerettet. Es muss nun innerhalb der Prozedur vom Programmierer ,,per Hand`` gesetzt werden. Dadurch kann die Residentfähigkeit eines Programmes erhalten werden. Auch hier findet sich ein Beispiel im Abschnitt 6.2.2.

Implementation
Implementation | n.a. | pro Modul | TRUE

Zu jeder Symboldatei erwartet der Linker auch eine Objektdatei. Besteht jedoch die Definition nur aus Typen- und Konstanten-Vereinbarungen oder der Deklaration absoluter oder externer Variablen und ist kein Code beim Import dieses Moduls auszuführen -- vom Compiler nur beim Implementations-Modul feststellbar --, erübrigt sich eine Objektdatei. In diesem Fall ist vor dem ersten Import oder der ersten Deklaration die Compiler-Anweisung

> `(*$ Implementation:=FALSE *)`

zu schreiben. Dies spart also des Schreiben eines ,,leeren`` ImplementationsModuls und die Ausführung unnützen Codes. Ein wenig Code muss sonst auch bei leeren Moduln erzeugt und durchlaufen werden.

Bezeichnerkontrolle
NameChk | n.a. | pro Modul | TRUE

In einer Symboldatei werden alle Bezeichner der Prozedurparameter abgelegt und deren Übereinstimmung in der Implementation überprüft. Stimmen die Namen nicht überein, erfolgt eine Fehlermeldung. Sollen die Bezeichner nicht vermerkt werden, kann in einem Definitionsmodul das Ablegen der Bezeichner mit

> `(*$ NameChk:=FALSE *)`

unterbunden werden. Der Nutzen liegt in kleineren und schneller einzulesenden Symboldateien. Sollen nur die abgelegten Bezeichner nicht überprüft werden, kann die Option zu Beginn des Implementationsmoduls angegeben werden.

Langwortgrenzen
LongAlign | l | stapelbar | TRUE

Normalerweise werden globale Variablen, die mehr als ein Byte belegen, auf Langwortgrenzen abgelegt. Dies ist manchmal zwingend notwendig (z.B. `DosD.FileInfoBlock`), lässt aber auch die Programme auf Prozessoren mit 32-Bit Datenbus -- 68020 und höher -- schneller laufen. Falls dies nicht nötig ist, kann durch die Angabe

> `(*$ LongAlign:=FALSE *)`

eine dichteres Aufeinanderfolgen der Variablen erreicht werden. Sie liegen dann auf Wortgrenzen. Näheres ist im Abschnitt 5.5.7, Seite zu finden.

Zeiger vergessen
Volatile | h | stapelbar | TRUE

Falls diese Option durch

> `(*$ Volatile:=FALSE *)`

auf `FALSE` gesetzt wird, versucht der Compiler, möglichst viele Zeiger in Adressregistern zu halten und wiederzubenutzen, was enorm Code sparen kann. Näheres kann man in Abschnitt 6.2.8, Seite nachlesen.

StackParameter
StackParms | z | stapelbar | TRUE

Normalerweise müssen Parameter, welche die Register D0 oder D1 belegen, bis zum endgültigen Prozeduraufruf zunächst auf dem Stack zwischengelagert werden, weil sie sonst durch andere Operationen zerstört werden könnten. Durch

> `(*$ StackParms:=FALSE *)`

wird erreicht, dass sie gleich, ohne Umweg über den Stack, in diesen Registern abgelegt werden, was Code und Laufzeit spart. Hierbei können jedoch Probleme auftreten; lesen Sie bitte Abschnitt 6.2.5, Seite !

Zeichenketten-Konstanten
CStrings | n.a. | stapelbar | TRUE

Da die Sonderbehandlung des Zeichens ,,`\``` in Zeichenketten-Konstanten (siehe 5.1.6, Seite ) zu Inkompatibilitäten führen kann, kann durch

> `(*$ CStrings:=FALSE *)`

auf die normale Bedeutung dieses Zeichens umgeschaltet werden.

Entwickler-Option
Joker | j | stapelbar | TRUE

Diese Option ist den Entwicklern des -Systems zu Testzwecken vorbehalten. Sie kann in jeder neuen Revision des Compilers eine andere Bedeutung haben und sollte deshalb vom Anwender keinesfalls eingesetzt werden!

-Modell
LargeVars | y | pro Modul | TRUE

Um die Anzahl und Grösse der globalen Variablen eines Moduls nicht einzuschränken, wird jedes Modul standardmässig im -Modell kompiliert. Durch die Angabe

> `(*$ LargeVars:=FALSE *)`

wird erreicht, dass es im -Modell kompiliert wird, also alle globalen Variablen dieses Moduls sind, was die Codegrösse verringert, das Programm beschleunigt und vor allem Bedingung für residentfähige Programme ist. Was hierbei zu beachten ist, wird in Abschnitt 5.1.12, Seite näher erklärt.

Daten in Chip
ChipDATA | n.a. | pro Modul | FALSE

Mit ist es möglich, globale Variablen mit einem vorinitialisierten Wert zu versehen:

> `VAR i:=INTEGER2;`

Diese Option entspricht in der Wirkungsweise der Option `ChipCODE`. Mit der Option `ChipDATA` werden die so vorinititialisierten globalen Variablen (5.1.8) im Chip-Memory abgelegt.

Daten müssen dann im Chip-Memory liegen, wenn die Custom Chips des Amigas darauf zugreifen müssen.

Daten in Chip
ChipBSS | n.a. | pro Modul | FALSE

Normalerweise wird für die nicht vorinitialisierten globalen Variablen eines Moduls kein bestimmter Speichertyp verlangt, das Betriebssystem vergibt den bestmöglichen. Durch die Anweisung

> `(*$ ChipBSS:=TRUE *)`

werden die globalen Daten des gesamten Moduls im Chip-Memory angelegt.

Der Einsatz dieser Option unterliegt den gleichen Einschränkungen wie die Option `ChipDATA`.

Code in Chip
ChipCODE | n.a. | pro Modul | FALSE

Hier gilt das gleiche wie unter `ChipDATA` und `ChipBSS` gesagte. Durch die Anweisung

> `(*$ ChipCODE:=TRUE *)`

wird der gesamte Code- und Konstanten-Bereich des Moduls im Chip-Memory abgelegt.

Zielprozessor
m68000...m68881 | 0...8 | pro Modul | 0

Diese Optionen sind ausschliesslich von der Kommandozeile durch die Ziffern `0`, `1`, `2`, `3`, `4` und `8` zu setzen. Sie dienen dazu, den Zielprozessor für den erzeugten Code festzulegen und so den optimalen Code zu erzeugen. Der Zielprozessor muss dabei nicht unbedingt identisch mit dem Prozessor des eigenen Amigas sein.

Standardeinstellung ist ,,`0```, d.h. der Compiler generiert Code, der auf allen Prozessoren der MC68000er-Familie lauffähig ist.

Bei der bedingten Kompilierung sind die in der Tabelle angegebenen Namen in `IF`-Abfragen erlaubt. Dabei ist zu beachten, dass all diese Optionen in gegenseitiger Abhängigkeit stehen, wie in Tabelle 2.5 zu sehen und unter 5.1.11, Seite beschrieben ist.

Unterabschnitte

- Optionen der Kommandozeile

Nächste Seite: Optionen der Kommandozeile Aufwärts: Der Compiler Vorherige Seite: Compiler-Ausgaben im Quelltext