I search for solutions in this order: Past Code, Unreal Source, Wiki, BUF, groups.yahoo, google, screaming at monitor. – RegularX

Difference between revisions of "Legacy:Preprocessor"

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search
m (deleting because of duplication, will redirect this page.)
(One intermediate revision by one other user not shown)
Line 1: Line 1:
Using the UT3 PreProcessor
 
  
=Introduction =
 
 
The UT3 PreProcessor is functional and while it seems to be lacking in documentation (at least that is available to the mod community) it works ok as a basic pp.
 
 
There are other preprocessors of course.  I believe I've seen several UnrealScript specific ones and there are always things like [http://www.cabaret.demon.co.uk/filepp/ filepp] which is just totally awesome.  You could use a C preprocessor as well, or something like perl's [http://www.tt2.org Template Toolkit].
 
 
However, should you choose to use the inbuilt preprocessor, here is a guide to what has been discovered so far.
 
 
=features =
 
 
* Basic if/else/elsif/endif directives
 
* Include capability
 
* Define preprocessor symbols
 
* Simple "literal" macro replacement
 
* Macros that can take arguments
 
* Multi-line Macros
 
* Some integration with Editor.Make
 
* ??? There must be more - please contribute your knowledge!
 
 
=usage =
 
 
The usage is simple and rather straight forward.  All directives are initiated with the backtick ( ` ) symbol.
 
 
==Defining Macros... ==
 
 
Here are some examples of defining macros and symbols:
 
 
<uscript>
 
`define MyVersion "1.3.20"
 
`define MyClass class'MyPackage.MyClass'
 
`define LogError(txt) LogInternal( GetFuncName()$":"$ `txt , 'Error')
 
`define LogDebug(txt) LogInternal( GetFuncName()$":"$ `txt , 'Debug')
 
`define MyAssert(condition) if( `condition ) { `LogError("Assert failed: `condition"); }
 
`define NameOf(var) ( ( `var == `var ) ? '`var' : '`var' )
 
</uscript>
 
 
==Conditional... ==
 
 
Standard if/elsif/else/endif clauses can be used.  At the moment, the conditions that can be evaluated by these clauses seem to be somewhat limited to the following:
 
 
<uscript>
 
`notdefined( SYMBOL )
 
`isdefined( SYMBOL )
 
</uscript>
 
 
There must be other preprocessor functions that can be used as well - but those are all you need to accomplish quite a bit:
 
 
<uscript>
 
`define MyVersion "1.3.20"
 
`define MyClass class'MyPackage.MyClass'
 
`define LogError(txt) LogInternal( GetFuncName()$":"$ `txt , 'Error')
 
`define MyAssert(condition) if( `condition ) { `LogError("Assert failed: `condition"); }
 
 
`if(`isdefined(DEBUG))
 
 
`define LogDebug(txt) LogInternal( GetFuncName()$":"$ `txt , 'Debug')
 
`define NameOf(var) ( ( `var == `var ) ? '`var' : '`var' )
 
 
`else
 
 
`define LogDebug(txt)
 
`define NameOf(var) '`var'
 
 
`endif
 
 
</uscript>
 
 
==Including Source... ==
 
 
You may use the include directive to incorporate content.  The convention for "header files" seems to be to use the extension: .uci
 
 
<uscript>
 
class MyMutator extends Mutator;
 
 
`include( MyPackage/Classes/MyStdInc.uci )
 
 
function PostBeginPlay()
 
{
 
    `MyDbg("MyCoolMutator, Version: " $ `MyVersion );
 
    // whatever....
 
}
 
</uscript>
 
 
==Things to investigate ==
 
 
The '#' symbol seems to be recognized:
 
 
<uscript>
 
// Not sure what this is - it may be for positional arguments or number of arguments supplied to macros.  More investigation is needed.
 
 
`#()
 
 
</uscript>
 
 
Enclosing symbols in '{' and '}' seems to have some purpose, not sure what it is but, I think it may mean "evaluate to empty string and do not produce an error if the symbol/macro is not defined." like so:
 
 
<uscript>
 
 
`if(`isdefined(MY_UNIT_TEST))
 
`define FuncScope public
 
`endif
 
 
`{FuncScope} MyCoolFunction()
 
{
 
  // whatever...
 
}
 
 
</uscript>
 
 
==Line Continuation and Multi Line Macros ==
 
 
You may wish to continue long lines or create multi-line macros.  You can continue lines with a backslash.  If you want your macros to be "multi-line" then you can place a "\n" at the end of the line.
 
 
Example source:
 
 
<uscript>
 
var int SwapTmp;
 
`define SwapInt(a,b) SwapTmp = `a; \
 
                    `a = `b; \
 
                    `b = SwapTmp
 
 
var array<string> Messages;
 
`define DefaultMessages \
 
  Messages(0)="Hello World" \n \
 
  Messages(1)="Headshot!!!" \n
 
 
class MyClass extends Info;
 
 
function PostBeginPlay()
 
{
 
  Swap(MyKills,MyHealth);
 
}
 
 
defaultproperties
 
{
 
  `DefaultMessages
 
}
 
 
</uscript>
 
 
The above would result in something like:
 
 
<uscript>
 
var int SwapTmp;
 
 
 
 
 
 
 
class MyClass extends Info;
 
 
function PostBeginPlay()
 
{
 
  SwapTmp = MyKills; MyKills = MyHealth; MyHealth = SwapTmp;
 
}
 
 
defaultproperties
 
{
 
  Messages(0)="Hello World"
 
  Messages(1)="Headshot!!!"
 
}
 
 
</uscript>
 
 
=Caveats =
 
 
==Line Numbers in warning/error output ==
 
 
Unless you use the `include() directive, you should not have a problem with this.  If however, you choose to
 
 
use the `include() directive then when your code has a warning or error it is quite likely that the line
 
 
number reported by the compiler will be inaccurate.
 
 
_[BIA]DarthMushak_ : I have written a perl script that will launch "ut3 make" and parse the resulting output before displaying it, adjusting line numbers as necessary.  If anyone is interested, let me know.
 
 
==white space ==
 
 
*Caution* you must be aware of how the UT3 preprocessor interprets whitespace!  If there is no whitespace between the end of your macro definition and the newline, then when the preprocessor inserts the result, it will *eat all the whitespace on its RHS* - so:
 
 
<uscript>
 
1: `define MyType int\n
 
2: \n
 
3: var `MyType Foo;\n
 
4: \n
 
5: `define MyOtherType string \n
 
6: \n
 
7: var `MyOtherType Bar;\n
 
</uscript>
 
 
Assuming that the "\n" chars in the code above are the newlines, the above code would effectively produce the following:
 
 
<uscript>
 
1:
 
2:
 
3: var intFoo;
 
4:
 
5:
 
6:
 
7: var string Bar;
 
</uscript>
 
 
So, be careful with the whitespace!
 
 
=Integration with Editor.Make ( ut3 make ... ) =
 
 
While you are free to define symbols such as DEBUG and FINAL_RELEASE via preprocessor directives it is probably best if you leverage the inbuilt support for these two via command line switches to the "make" Commandlet.
 
 
Here is an example snippet of a class file that will be used to clarify the following examples:
 
 
===DEBUG ===
 
 
By supplying the switch *-debug* to make, the symbol "DEBUG" will be defined globally in all classes during the parsing phase.
 
 
<uscript>
 
ut3 make -debug
 
</uscript>
 
 
===FINAL_RELEASE ===
 
 
By supplying the switch *-final_release* to make, the symbol "FINAL_RELEASE" will be defined globally in all classes during parsing phase.
 
 
===RELEASE ===
 
 
If you supply neither *-final_release* or *-debug* then the code will be built for "release".
 
 
 
 
=More to come =
 
 
Stay tuned!  If you learn more, please update this page.  Thanks!
 

Revision as of 22:51, 21 April 2010