This article is from the Amiga FAQ, by Ignaz Kellerer with numerous contributions by others.
Pragmas are special compiler commmands which control certain features of a C-compiler. Two problems arise when using pragmas: 1. Pragmas are compiler specific. You cannot expect that one compiler will understand pragmas of another compiler, even if both run on the Amiga.
2. You are not guaranteed that a compiler ignores pragmas, that he doesn't understand. Even more: It might not help, to use something like this: #ifndef MY_COMPILER #pragma DoAnything #endif
A workaround is to put pragmas in a special include file (BTW, the same holds true for statements like #asm (Aztec-C) or #extern (C++) and replace the above with #ifndef MY_COMPILER #include <mypragmas.h> #endif
But what do pragmas on the Amiga? The most common usage (not the only, but most meant when talking about pragmas) is to tell the compiler about how to call library functions: Simple C functions expect their arguments on the stack, but library functions want their arguments in special processor registers and additionally the `library base' in register a6. Lets have a look at a pragma command of the Aztec-Compiler. #pragma amicall(SysBase,0xd2,FreeMem(a1,d0))
This tells the compiler to put the first argument of FreeMem in register a1, the second in register d0 and the value of the variable SysBase in register a6. Maxons pragmas look the same, Dice pragmas and SAS pragmas look a bit more complicated; #pragma libcall SysBase FreeMem d2 0902
Here d2 is (like 0xd2 above) the `library vector offset' (see below), the digits 09 are codes for the argument register in reversed order (Register codes are 0=d0, 1=d1, .., 8=a0, 9=a1, a=a2, ..), the following 0 is the result's registerä(always d0))and the final digit 2 is the number of arguments.
A command `FreeMem(fib,sizeof(*fib);' could produce the following code, if the compiler has seen a pragma statement like above: move.l _fib,a1 move.l 260,d1 ; sizeof(struct FileInfoBlock) move.l _SysBase,a6 jsr -0xd2(a6) ; 0xd2 = _LVOFreeMem
Calling FreeMem in that way is shorter and faster than pushing the arguments on the stack, calling a function _FreeMem which would do just the same like the above code by pulling the arguments from the stack.
The best way to use pragmas is to include statements like the following in your program: /* SAS/C, Dice and GNU-c (since version 2.6.1) make it */ /* very simple: */ #if defined(__SASC) || defined(_DCC) || defined(__GNUC__) #include <proto/exec.h> #else
/* Get the prototype for the function; note, that this */ /* is compiler independent. */ #include <clib/exec_protos.h>
/* Get the pragma; compiler dependent, but most pragmas */ /* are in files with the same name. */ #ifdef AZTEC_C #include <pragmas/exec_lib.h> #elif defined(__MAXON__) #include <pragmas/exec_pragmas.h> #endif
/* Declare the SysBase variable */ extern struct ExecBase *SysBase; #endif
The above example can be compiled on all these compilers and produce the best code. (Besides, the proto/*.h-files do nothing else than reading clib/*_protos.h and pragmas/*_pragmas.h with #include and then declare the SysBase variable.)
A final question arises: How to get the pragmas? Most compilers have them included. However, sometimes you want to produce pragmas for yourself, for example if you are using new libraries or new versions with additional functions. In that case you can produce them from the so-called `FD' files which should be a part of the developer docs of the library. (The NDU has a directory FD which contains FD files for all libraries and devices of the OS. see Includes) Most compilers have a utility with the name `fd2pragma' or similar included which can do that for you. A freely distributable version which can produce pragmas for Aztec, Dice, SAS and Maxon as well as LVO files for assembler and stub routines for the tag versions is available on Aminet (`dev/misc/fd2pragma2_0.lha' and on the Fish CDs.
For pragmas under gcc see Inline Headers.