PreProcessor Commands: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m ('recognised' is correct as original author is not US American)
(attempt to improve readability, requires technical proof reading)
Line 1: Line 1:
=Introduction =
=Introduction =


 
Preprocessor commands refer to the C(++) syntax used by the engine to 'pre process' the text inside a config.cpp, mission.sqm, or description.ext file. In fact, preprocessor commands apply to '''any''' BI game 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.  
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:
There are six preprocessor commands recognised by the OFP and ArmA engine:
Line 16: Line 11:
  #ifndef
  #ifndef
  #endif
  #endif
Besides of commands, inside of defines it is possible to use token concatenation operator ## and stringize operator #.


==Note for experienced users==
==Note for experienced users==


The preprocessor mimics a subset of [http://en.wikipedia.org/wiki/C_preprocessor 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.
The preprocessor mimics a subset of [http://en.wikipedia.org/wiki/C_preprocessor 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, especially when using token concatenation operator, may produce different results than in C.


= Preprocessor commands =
= Preprocessor commands =
Line 27: Line 20:
==#include==
==#include==


Syntax
'''Syntax:'''
 
  #include <PathAndFileName>
  #include <PathAndFileName> // '''note''' no semicolon
  #include "PathAndFileName"
  #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 <u>no consequence</u>. 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 <u>beginning of the included file</u> 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===
The purpose of an include statement is to wedge in further statements into the current body of text. The reason for doing so, in BI games at least, is artistry. To break up one large confusing text many pages long into smaller, more manageable chunks.


Paths to files in OFP do '''not''' follow convention, or in some cases, logic.
The number of 'chunks' (ie, the number of included files) is solely at the author's discretion. In general, they will put similar elements together. For example, all icons will be in one file, all buildings in another, all cars in another, and so on. It is particularly common in the case of veteran authors to put base characteristics of similar 'models' into a single 'base' file, and then include this file into multiple variations of that base model. For example, a base file may define a soldier with khaki trousers. A second soldier class could include this standard base, and then define specific variations (which may change the trousers to pink, and so on). The base characteristics of the model do not need to be repeated in the main body of the text for the second soldier, as it's duplicating work and contains no new information.


The following is <u>specific</u> 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)
From the perspective of the game engine, the use of #include files is of <u>no consequence</u>, since the engine effectively processes all files as one file. All of the 'chunks' (the #included files) are merged into a single file for the purpose of compiling. Irrespective of how many #included files are used, the result is a single config.bin (config.bin is the resultant output of all this processing).


#include "'''Any'''Addon\'''Any'''PathInTheAddon\SomeFile.SomeExtension"
Processing continues at the beginning of the included file until it's end, 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 which circumstance, processing continues at the beginning of that included file, and so on.


Take note that this is contrary to what you do with other file references.
Example:
#include "someAddon\somePathInTheAddon\someFile.someExtension"


There is NO preceeding backslash.
Note that the #include syntax string does not use a preceding backslash, unlike other file references (such as icons or models, etc.) used in BI game files. Also note, that there is no default file extension, and no trailing semi-colon.


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


==#define==
==#define==


For reasons lost in the mysts of Kernighan and Ritchie, this is referred to by the riduculous term 'macro'.
'''Syntax:'''
 
#define NAME VALUE
It is a 'macro' in the same way macros are used in Microsoft word, it can expand into a (very large) sequence of keystrokes.
Within defines arguments, the token 'concatenation operator' ##, and 'stringize operator' # may be used.
 
For the sensibly minded you can effectively 'see' #defines as
 
#define THIS  = THAT


Define statements may be referred to by the term 'macro'. It is a macro in the same way macros are used in Microsoft Word - one macro can expand into a (very large) sequence of keystrokes. You can effectively understand #defines as
#define THIS = THAT
For example:
  #define true  1
  #define true  1
  #define false 0
  #define false 0
 
Macros can be expanded to the following example:
For the non- sensibly minded and insane, you can indeed expand this 'macro'
 
  #define ICONS(icn) icon=\SomeAddon\icons\##icn; \
  #define ICONS(icn) icon=\SomeAddon\icons\##icn; \
                     model=\SomeAddon\##icn.p3d; \
                     model=\SomeAddon\##icn.p3d; \
                     picture=\SomeAddon\##icn.paa
                     picture=\SomeAddon\##icn.paa
 
Then, using
Then, using
 
  ICON(Peter);
  ICON(Peter);
  ICON(Fred);
  ICON(Fred);
 
will be expanded during processing into:
will expand into
 
  icon=\SomeAddon\icons\Peter;
  icon=\SomeAddon\icons\Peter;
  model=\SomeAddon\Peter.p3d;
  model=\SomeAddon\Peter.p3d;
Line 96: Line 64:
  picture=\SomeAddon\Fred.paa;
  picture=\SomeAddon\Fred.paa;


The <u>purpose</u> 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 expanded macros as illustrated above is to allow simplified syntax, and to reduce typing load (and the likelihood of typos). In the case of the first example above, the #define macro creates more explicit, legible files, at the expense of increased typing.
 
The <u>purpose</u> of the first form of #define (as illustrated above) is to INCREASE typing but become more explicit, more legible.


motorcylce=false;


==#undef==
==#undef==
This will undefine ("delete") a macro previously set by the use of #define.
'''Syntax:'''
 
Syntax
 
  #undef NAME
  #undef NAME


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




==#ifdef==
==#ifdef==
Syntax
'''Syntax:'''
 
  #ifdef NAME
  #ifdef NAME
   ...text that will be used if NAME is defined...
   ...text that will be used if NAME is defined...
Line 120: Line 82:


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


==#endif==
==#endif==

Revision as of 15:36, 5 September 2008

Introduction

Preprocessor commands refer to the C(++) syntax used by the engine to 'pre process' the text inside a config.cpp, mission.sqm, or description.ext file. In fact, preprocessor commands apply to any BI game 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

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, especially when using token concatenation operator, may produce different results than in C.

Preprocessor commands

#include

Syntax:

#include <PathAndFileName>
#include "PathAndFileName"

The purpose of an include statement is to wedge in further statements into the current body of text. The reason for doing so, in BI games at least, is artistry. To break up one large confusing text many pages long into smaller, more manageable chunks.

The number of 'chunks' (ie, the number of included files) is solely at the author's discretion. In general, they will put similar elements together. For example, all icons will be in one file, all buildings in another, all cars in another, and so on. It is particularly common in the case of veteran authors to put base characteristics of similar 'models' into a single 'base' file, and then include this file into multiple variations of that base model. For example, a base file may define a soldier with khaki trousers. A second soldier class could include this standard base, and then define specific variations (which may change the trousers to pink, and so on). The base characteristics of the model do not need to be repeated in the main body of the text for the second soldier, as it's duplicating work and contains no new information.

From the perspective of the game engine, the use of #include files is of no consequence, since the engine effectively processes all files as one file. All of the 'chunks' (the #included files) are merged into a single file for the purpose of compiling. Irrespective of how many #included files are used, the result is a single config.bin (config.bin is the resultant output of all this processing).

Processing continues at the beginning of the included file until it's end, 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 which circumstance, processing continues at the beginning of that included file, and so on.

Example:

#include "someAddon\somePathInTheAddon\someFile.someExtension"

Note that the #include syntax string does not use a preceding backslash, unlike other file references (such as icons or models, etc.) used in BI game files. Also note, that there is no default file extension, and no trailing semi-colon.


#define

Syntax:

#define NAME VALUE

Within defines arguments, the token 'concatenation operator' ##, and 'stringize operator' # may be used.

Define statements may be referred to by the term 'macro'. It is a macro in the same way macros are used in Microsoft Word - one macro can expand into a (very large) sequence of keystrokes. You can effectively understand #defines as

#define THIS = THAT

For example:

#define true  1
#define false 0

Macros can be expanded to the following example:

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

Then, using:

ICON(Peter);
ICON(Fred);

will be expanded during processing 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 allow simplified syntax, and to reduce typing load (and the likelihood of typos). In the case of the first example above, the #define macro creates more explicit, legible files, at the expense of increased typing.


#undef

Syntax:

#undef NAME

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


#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.