<< WindowPtr >> Fehlende Funktionen
#ifndef MY_COMPILER #pragma DoAnything #endif
#ifndef MY_COMPILER #include <mypragmas.h> #endif
Aber was machen Pragmas auf dem Amiga? Meistens werden sie verwendet,
um dem Compiler mitzuteilen, wie gewisse Library-Funktionen aufgerufen
werden. (Tatsächlich wird fast immer diese Verwendung gemeint, wenn
Amiga-Besitzer über Pragmas sprechen.) Gewöhnliche C-Funktionen erwarten
ihre Argumente auf dem Stack, Library-Funktionen dagegen in bestimmten
Registern. Ferner erwarten sie den Library-Base-Pointer
in Register a6.
Betrachten wir eine Pragma-Anweisung von Aztec-C:
#pragma amicall(SysBase,0xd2,FreeMem(a1,d0))Dies weist den Compiler an, das erste Argument in Register a1 und das zweite in d0 zu laden. Ferner wird der Inhalt der Variablen SysBase in Register a6 geladen. Maxon-Pragmas sehen genauso aus, Dice- und SAS-Pragmas sind allerdings etwas komplizierter:
#pragma libcall SysBase FreeMem d2 0902Hier ist d2 (wie 0xd2 oben) der
Library-Vektor-Offset
(siehe
nächstes Beispiel). Die letzte Ziffer ist die Zahl der Argumente, die
davorstehende 0 ein Code für das Register mit dem Ergebnis und die davor
stehenden Ziffern sind Codes für die Register mit den Argumenten in
verkehrter Reihenfolge. (Die Codes bedeuten 0=d0, 1=d1, .., 8=a0, 9=a1, a=a2,
..)
Ein Kommando wie `FreeMem(fib,sizeof(*fib);' würde ein Compiler nun in folgenden Code übersetzen:
move.l _fib,a1 move.l 260,d1 ; sizeof(struct FileInfoBlock) move.l _SysBase,a6 jsr -0xd2(a6) ; 0xd2 = _LVOFreeMemFreeMem in dieser Art aufzurufen ist kürzer und schneller als zunächst die Argumente auf den Stack zu legen und dann eine Funktion _FreeMem aufzurufen, die letzten Endes doch nur dasselbe tun und die Argumente vom Stack in dieselben Register laden würde.
Das Portierungsproblem der Pragmas umgeht man, indem man sie folgendermaßen in den eigenen Quelltext einbindet:
/* SAS/C, Dice und GNU-c (ab Version 2.6.1) machen es */ /* ganz einfach: */ #if defined(__SASC) || defined(_DCC) || defined(__GNUC__) #include <proto/exec.h> #else /* Lade den Funktionsprototyp. Dieser ist nicht vom */ /* verwendeten Compiler abhängig. */ #include <clib/exec_protos.h> /* Pragmas sind vom Compiler abhängig, aber wenigstens */ /* die Namen der Dateien mit Pragmas sind relativ */ /* einheitlich. */ #ifdef AZTEC_C #include <pragmas/exec_lib.h> #elif defined(__MAXON__) #include <pragmas/exec_pragmas.h> #endif /* Deklariere SysBase-Variable */ extern struct ExecBase *SysBase; #endifDas obige Beispiel kann problemlos mit allen angegebenen Compilern verwendet werden und produziert optimalen Code. (Die proto/*.h-Files machen übrigens auch nichts anderes als clib/*_protos.h und pragmas/*_pragmas.h mit #include einzulesen und dann die SysBase-Variable zu deklarieren.)
Eine abschließende Frage bleibt allerdings: Wie bekommt man die Pragmas?
Die meisten Compiler haben bereits fertige Pragmas im Lieferumfang.
Allerdings hilft das nicht, wenn man z.B. eine neue Library benutzen
möchte oder nur die Pragmas einer veralteten Version hat. In diesem Fall
kann man die Pragmas selbst aus den sogenannten FD
-Files erzeugen.
Dazu haben die meisten Compiler ein Utility namens fd2pragma
.
(Das NDU hat z.B. ein Directory namens FD, in dem die FD-Files aller
Libraries und Devices des OS enthalten sind. siehe Abschnitt Wo bekomme ich die Amiga-Include-Dateien?) Es gibt
auch ein frei kopierbares fd2pragma, das Pragmas für Aztec, Dice, SAS und
Maxon sowie LVO-Files für den Aztec-Assembler und eventuelle Tag-Versionen
produziert. (Aminet, `dev/misc/fd2pragma2_0.lha' oder auf den
Fish-CDs)
Für Pragmas unter dem gcc siehe Abschnitt Inline-Dateien.
<< WindowPtr >> Fehlende Funktionen