The Basics of Programming

7. Preprocessor Commands

All C compilers support a special set of commands that govern how the compiler manages and controls the code produced. The commands are not included in the final compiled code but it does affect how and what code is compiled. A list of common commands is explained here:

a) #INCLUDE

The command is used to include code from other files especially header files. A header file usually includes function definitions, structure or class definitions, external references, constants, and other things that you do not want to clutter your main code files. There are two formats:

#INCLUDE <file.h>
#INCLUDE "file.h"

The difference is that the first will use file.h from the default system include folders where the C compiler and Operating system header files are stored. The section format specifies a file.h from the same folder where your program source code is kept.

b) #DEFINE, #UNDEF

This command defines constants or functions for you by the program and can be also be used by #IFDEF to determine environmental features of the target computer such as Operating System Version, CPU type and other features. The #UNDEF command will undefine a pre-existing name such as some built in function. The format of the command is:

#DEFINE name value
#DEFINE name(parameter) expression
#UNDEF name

The value can be optional, so that the name is defined but has no value.
e.g.

#DEFINE PI 3.41
#DEFINE VAT 20
#DEFINE AMIGAOS3
#DEFINE RADTODEG(x) (x * 57.29578) /* Convert Radians to Degrees */
#UNDEF strcmp /* undefine strcmp */

c) Conditional Compiling (#IF, #IFDEF, #IFNDEF, #ELSE, #ELIF, #ENDIF)

These commands can be used to control what code is included in the compilation process by using conditional commands

#IF can be used with a expression which is calculated during compile time (not runtime) and determines if the code between #IF and #ELSE or #ENDIF is included in the compile.e.g.

#IF __oslibversion >= 40  
   /* statements here if the OS version is at least v40 or later */   
#ENDIF 

#IFDEF is used with a defined name (see #DEFINE) which has or has not be defined and include the code below.
e.g.

#IFDEF AMIGAOS 
  /* statement for amigaOS */
#ELSE
  /* statements for another OS */
#ENDIF

The opposite command is called #IFNDEF (if not defined) with a defined name.

#IFNDEF AROS    
   /* statement for Non-AROS OS */ 
#ELSE /* statements for aros OS */ #ENDIF

d) #WARNING and #ERROR messages.

These commands will display a warning or error message when compiling the program.
e.g.

#WARNING "Do not use ABC, which is deprecated. Use XYZ instead."
#ERROR "Error. This cannot be done here."

e) #PRAGMA. Defines how library function functions by moving the parameters into registers, loads library base into A6 and calls the function.

The #PRAGMA statement tells the compiler how to process OS and user functions, they are usually defined in pragma header files. There are several formats

#PRAGMA libcall base function offset magic
#PRAGMA amicall(base, offset, [retreg=]function(reg1 [,reg2] ....)
#PRAGMA syscall function offset magic
#PRAGMA tagcall various parameters
#PRAGMA regcall([D0=]function(reg1 [,reg2] ...))

base = Pointer or name of the library base
function = Name of the function to call
offset = The offset from the base of the Library (see .fd files)
magic = Register conventions expected by the function
retreg = Return register for return value
regx = Registers to pass parameters to