PreProcessor Commands: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
(→‎Introduction: token concatenation)
m ('recognised' is correct as original author is not US American)
Line 8: Line 8:
The majority use however is in addons, and specifically, the config.cpp of the addon.
The majority use however is in addons, and specifically, the config.cpp of the addon.


There are six preprocessor commands recognized by the OFP and ArmA engine:
There are six preprocessor commands recognised by the OFP and ArmA engine:


  #include
  #include

Revision as of 22:01, 7 January 2008

Introduction

Preprocessor commands refer to the C(++) syntax used by the engine to, well, 'pre process' the text inside a config.cpp, mission.sqm, description.ext.

In fact, preprocessor commands (can) apply to any ofp text file containing class statements, since these 'statements' are scrunched by the engine's internal C processor.

The majority use however is in addons, and specifically, the config.cpp of the addon.

There are six preprocessor commands recognised by the OFP and ArmA engine:

#include
#define
#undef
#ifdef
#ifndef
#endif

Besides of commands, inside of defines it is possible to use token concatenation operator ## and stringize operator #.

Note for experienced users

The preprocessor mimics a subset of C preprocessor. While basic functionality is similar, the preprocessor is not fully C-conformant, as order of substitution of arguments in macro invocation is different than in C, which means some intricate nested macro constructs, esp. when using token concatenation operator, may produce different results than in C.

Preprocessor commands

#include

Syntax

#include <PathAndFileName> // note no semicolon
#include "PathAndFileName" // mutually the same.

The base purpose of this statement is to wedge in further statements into the current body of text. The reason for doing so, in ofp at least, is artistry. To break up one large confusing text many many pages long, into manageable chunks.

The amount of 'chunks', ie, the number of included files, is solely dependent on how the author feels about it. In general, they will put similar elements together. All icons, all bulidings (versus trees) all cars (versus men) and so on. It is particularly common in vintage addons (people who have had some years in creating them) to put base charactersics of all the 'models' in one, base file, and then attach it to flavours of that base. Ie a base man with kahki trousers as standard included in files that change the trousers to pink, and so on. Ie, the base characterstics of the model, are NOT in the 'main' body of text as it's noisy and hardly worth looking at. A better example is one of weapons. Irrespective of the several addons made, they all include this one, weapon file, since they all will use AK47's with tangerine hand grenades with yellow spots. If some use M16's, no matter, you can be _certain_ an M16 is _also_ described in this base, weapon file, #included in all other files that need acces to M16's!

THE ENGINE DOES NOT CARE

From the perspective of the engine, it is of no consequence. Effectively the engine processes all files as one file. All of the chunks, all of the 'wedges', all of the #included files are merged into one, single file, for the purpose of compiling. Of a certainty, irrespective of how many #included files, you only get ONE, config.bin. (Config.bin, is the resultant output of all this processing)


Processing continues at the beginning of the included file until it's EOF. At which point, processing continues at the statement after the initial #include.

Thus, anything required by that included file (if anything at all), must have 'appeared' _before_ the include statement.

It is quite common, for included files, to have, #include statement(s) of their own.

Under this circumstance, processing continues at the beginning of _that_ included file, and so on.

Path name

Paths to files in OFP do not follow convention, or in some cases, logic.

The following is specific to the #include statement as applied by the engine. Do not attempt to use the following when utilising other file references (such as icons or models eg)

#include "AnyAddon\AnyPathInTheAddon\SomeFile.SomeExtension"

Take note that this is contrary to what you do with other file references.

There is NO preceeding backslash.

Also note, that there is no default extension. It's called, whatever you want to call it (if anything at all)

#define

For reasons lost in the mysts of Kernighan and Ritchie, this is referred to by the riduculous term 'macro'.

It is a 'macro' in the same way macros are used in Microsoft word, it can expand into a (very large) sequence of keystrokes.

For the sensibly minded you can effectively 'see' #defines as

#define THIS  = THAT
#define true  1
#define false 0

For the non- sensibly minded and insane, you can indeed expand this 'macro'

#define ICONS(icn) icon=\SomeAddon\icons\##icn; \
                   model=\SomeAddon\##icn.p3d; \
                   picture=\SomeAddon\##icn.paa

Then, using

ICON(Peter);
ICON(Fred);

will expand into

icon=\SomeAddon\icons\Peter;
model=\SomeAddon\Peter.p3d;
picture=\SomeAddon\Peter.paa;
icon=\SomeAddon\icons\Fred;
model=\SomeAddon\Fred.p3d;
picture=\SomeAddon\Fred.paa;

The purpose of expanded macros (as illustrated above) is to reduce noise levels. To use a simple syntax to be legible, AND TO REDUCE TYPING. Reduction in typing means less typos.

The purpose of the first form of #define (as illustrated above) is to INCREASE typing but become more explicit, more legible.

motorcylce=false;

#undef

This will undefine ("delete") a macro previously set by the use of #define.

Syntax

#undef NAME


#ifdef

Syntax

#ifdef NAME
  ...text that will be used if NAME is defined...
#endif


#ifndef

Syntax

#ifndef NAME
  ...text that will be used if NAME isn't defined...
#endif

#endif

This ends a conditional block as shown in the descriptions of #ifdef and #ifndef above.