2.2 Preprocessor directives
-----------------------------
C-- has no preprocessor, but several functions greatly resemble those of
the C preprocessor.
These so-called translator directives, which all begin with ? or #, are
listed below with their purposes:
? align [val] aligns program data to even address
(default) or to address which is a multiple
of the value 'val'.
? aligncode [val] aligns program code to even address
(default) or to address which is a multiple
of the value 'val'. Use 0x90 (NOP) to fill
unused memory cells
? aligner (aligner value) defines value of insertion byte
? alignword (TRUE or FALSE) permits or do not permits alignment of
variables of type word an int to even
address (default TRUE)
? argc (TRUE or FALSE) does or does not include alternate
command-line handler
? atexit adds support for ATEXIT() to startup code
? code32 (TRUE/FALSE) does or does not permit generation of 32-bit
code
? codesize optimizes code size (at the expense of
speed)
? compilerversion indicates which version of the compiler is
needed to compile this program
? ctrl_c (TRUE or FALSE ) permits or does not permit the program to
ignore Ctl-C [default FALSE]
? dataseg (value) tells the compiler the RAM segment address
for variables when compiling ROM BIOS.
? define (identifier) (token) defines the identifier.
? DOSrequired (number) specifies the minimum required version of
DOS: high-order byte - version number,
low-order byte - modification number.
0x0101 for version 1.1 DOS
0x0315 for version 3.21 DOS
0x0303 for version 3.3 DOS
0x0600 for version 6.0 DOS
0x0602 for version 6.2 DOS and etc.
? dosstring (TRUE/FALSE) tells the compiler that '$' must be used as
the string end
? else generates generates alternate code if ?ifdef of
?ifndef are FALSE.
? endif indicates the end of action of the
directives ifdef or ifndef
? fastcallapi (FALSE/TRUE) does or does not permit generation of a fast
call to API functions (by default
permitted). Used in compiling Windows
programs.
? fixuptable (TRUE/FALSE) does or does not permit creation of FixUp
tables (by default does not permit this).
Used when compiling Windows programs.
? ifdef (identifier) if an identifier is defined, returns TRUE,
otherwise FALSE
? imagebase value assigns the address of Image Base (by
default 0x400000). Used in compiling
Windows programs.
? ifndef (identifier) if an identifier is defined, returns FALSE,
otherwise TRUE
? include ("filename") includes another file
? includepath ("path") tells the compiler where to search for
included files
? initallvar initializes to 0 all uninitialized
variables
? jumptomain (NONE, SHORT, NEAR or FALSE)
specifes type of jump to main() (default
NEAR)
? maxerrors (number) maximum number of errors found after which
the translator stops (default 16)
? movedatarom (TRUE/FALSE) tells compiler to move data from ROM to RAM
? parsecommandline (TRUE or FALSE)
includes a block of code for parsing the
command line (default FALSE)
? pragma can declare several other directives
? print (number or string) prints to screen a number or string
? printhex (number) prints to screen a hexadecimal number
? randombyte inserts a random value byte into the program
code
? resize (TRUE or FALSE) includes a function for changing the size of
the memory block allocated by the program
after it is running to the minimum required
(default TRUE)
? resizemessage (string) message printed to screen before emergency
interrupt of the program if the change in
size of the memory block allocated by the
program was not performed
? setdinproc this directive causes the compiler to
immediately insert into the code of the
program being compiled all dynamic
functions called earlier
? sizerom (value) tells the controller ROM size
? speed optimizes speed (default) at the expense of
code size
? stack (number) defines the size of the program stack in
bytes
? startaddress (number) sets the start address of the beginning of
the code (default 0x100)
? startuptomain in .com files, places startup code in main()
? startusevar (number) indicates the address used by memory cells
for uninitialized variables
? sysattribute (value) sends the compiler the attribute of the
driver being created. By default 0x2000.
Works only with /SYS.
? sysname <text string> sends the compiler the name of the driver
being compiled. By default this is NO_NAME.
Names may be up to 8 characters long. Works
only with /SYS.
? syscommand <command_0>,<command_1>,...<command_n>;
required when creating drivers. Sends the
compiler a list of names of functions for
processing the driver commands. Works only
with /SYS.
? undef cancels constants declared by ? define
? use8086 limits compiler to generating object code
for 8086/8088 (default)
? use8088 limits compiler to generating object code
for 8088/8086.
? use80186 allows generation of object code commands
and optimization for 80186
? use80286 allows generation of object code commands
and optimization for processor 80286.
? use80386 allows generation of object code commands
and optimization for processor 80386.
? use80486 allows generation of object code commands
and optimization for processor 80486.
? usePentium allows generation of object code commands
and optimization for processor Pentium.
? useMMX allows generation of object code commands
and optimization for processor Pentium MMX.
? usestartup permits use of memory cells occupied by
startup code of program
? warning (TRUE or FALSE) does or does not permit output of warnings.
Works only within the current file and does
not affect included files.
? winmonoblock FALSE prevents placing tables of file format PE
into one section
2.2.1 ?ifdef/?ifndef
~~~~~~~~~~~~~~~~~~~~~
The directive '?ifdef' used to operate if there was a constant in the
code being compiled, regardless of its value, while ?ifndef operated only
if there was no constant Now ?ifdef operates only if there is a constant
which does not have the value FALSE, while ?ifndef operates both if there
is no constant and if the constant has the value FALSE.
The constants codesize and speed, which take on the values TRUE or
FALSE depending on optimization mode, are reserved for ?ifdef and
?ifndef. This can be used to create more flexible libraries.
You can check the CPU type for which you are compiling by using
statements like:
?ifdef cpu > 1 // if compiling for an 80186 or later cpu
?ifndef cpu >= 2 // -------//------------- an 80286 or later
?ifdef cpu == 3 // -------//------------- an 80386
?ifdef cpu != 0 // -------//------------- a cpu other than an 8086
?ifdef cpu < 3 // -------//------------- a cpu older than an 80386
?ifdef cpu <= 2 // -------//------------- an 80286 or older cpu
This is used to write code for specific cpu's.
2.2.2 ?initallvar
~~~~~~~~~~~~~~~~~~
When TRUE, switches on the mode in which all uninitialized variables
are set to zero and are located where they were declared. The practical
outcome is that uninitialized variables disappear, which may be useful
when writing drivers and TSRs.
If set to FALSE the mode is switched off (default FALSE).
2.2.3 ?usestartup
~~~~~~~~~~~~~~~~~~
Permits the compiler to reuse memory cells used by the startup code
to store uninitialized variables. This may be useful for obtaining more
compact code than in normal programs, in particular TSR's.
Used only for generating .com files.
2.2.4 ?startusevar
~~~~~~~~~~~~~~~~~~~
Indicates the starting address from which the compiler assigns memory
for uninitialized variables. For example, '?startusevar 0x53' instructs
the compiler to locate uninitialized variables starting at address 0x53.
This can be useful for obtaining more compact code, in the case of both
TSR's and ordinary programs.
Used only for generating .com files.
2.2.5 ?atexit
~~~~~~~~~~~~~~
Adds support for ATEXIT to the startup code, reserves space for
storing 16 function addresses, and changes the code of ABORT and EXIT.
ATEXIT registers the function whose address is passed to it as a
parameter of the program-termination function. This function is called at
program termination by the functions ABORT or EXIT or by the instruction
RET from main.
Up to 16 functions may be registered. They are called in the
opposite order from that in which they were registered.
2.2.6 ?startuptomain
~~~~~~~~~~~~~~~~~~~~~
Tells the compiler to do a 'jmp' to the beginning of main() at the
start of a file. Before starting to compile this function, the compiler
starts to compile the startup code and then continues compiling main().
Thus the startup code is not at the start of the file as is usually the
case, but in the body of main(). This can be usedful when compiling TSR's.
Used only in compiling .com files.
2.2.7 ?undef
~~~~~~~~~~~~~
Cancels constants declared by ?define. Used to modify the value of a
constant during compilation.
2.2.8 ?align and ?aligncode
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The directive '?align' does a single alignment of data to an even
address. If a value is included, alignment will be done to an address
which is a multiple of this value. For example, '?align 4' adds the data
segment to an address which is a multiple of 4. During alignment, bytes
whose values are defined by '?aligner' are inserted (default zero).
'?align' aligns only in the data segment. In memory models for which the
data and code segments coincide, this directive can also be used for
aligning the start of a function.
The directive '?aligncode [value]' does an alignment in the code
segment to an address which is a multiple of a value (by default to an
even address). The byte value used to fill unused memory cells is 0x90 -
the NOP instruction code. This value cannot be changed. The directive may
also be used within executable code. For instance, to obtain fast code
for a 486, align the start of functions and loops to an address which is
a multiple of 16.
2.2.9 ?pragma
~~~~~~~~~~~~~~
This multifunctional directive has its own directives:
option
Tells the compiler to include command-line options. Certain options
cannot be used, while others may be placed only at the start of the
source code. Example:
#pragma option w32c
Tells the compiler to produce a 32-bit console Windows file.
startup
Indicates the function to be executed before starting 'main'. The
format is as follows:
#pragma startup procname
There is no limit on the number of times this directive can be used
in a program, but in reality this is only a few thousand times.
line
Displays the current line number and file name, and optionally also
the string contents after the word 'line'. For example:
#pragma line information
Displays the line number and file name, as well as any message to the
right of the word 'line'.
resource
May have the values 'start' or 'end', which mark the start and end of
a resource block when it is used directly in the source code rather than
in a separate file. For example:
#pragma resource start
MyMenu MENU DISCARDABLE
BEGIN POPUP "Files",HELP
BEGIN
MENUITEM "Open", ID_OPEN
MENUITEM "Save", ID_SAVE
MENUITEM SEPARATOR
MENUITEM "Exit", ID_EXIT
END
MENUITEM "Other", 65535
END
#pragma resource end