Difference between revisions of "Precompiler definitions"

From FTE
Jump to: navigation, search
(Pragma (#pragma))
(#pragma warning)
Line 318: Line 318:
 
* enable, on: enable the chosen warning
 
* enable, on: enable the chosen warning
 
* disable, off: disable the chosen warning
 
* disable, off: disable the chosen warning
 +
* error: makes the warning fatal
 
* toggle: toggle the warning state
 
* toggle: toggle the warning state
  
 
See [[FTEQCC Warnings and Errors]] for all of the possibilities of <warningid>.
 
See [[FTEQCC Warnings and Errors]] for all of the possibilities of <warningid>.

Revision as of 04:08, 10 July 2015

Definitions

#define

Syntax: #define <defname>[(<macroparams>)] [<defvalue>]

Defines a precompiler define or macro.

  • <defname> contains the define name
  • <macroparams> contains a list of parameters, seperated by commas, to use with a macro (optional)
  • <defvalue> contains the define value (optional)

After statement parsing, <defname> is considered defined. Then, FTEQCC encounters <defname> or #<defname> during parsing, it will be replaced with <defvalue>, or <defname> will be erased if <defvalue> is not defined. If <macroparams> are defined, FTEQCC will use <defvalue> in the following fashion:

  • If a parameter in <macroparams> as an isolated token is found, it is replaced into the result.
  • If a parameter in <macroparams> is found with a preceding #, it is surrounded in quotes, then placed into the result.
  • If a parameter in <macroparams> is found with 2 preceding #, it is concatenated into the result.

Examples:

// Simple defines for use in precompiler control logic later on
#define MONSTERS
#define NEWWEAPONS
// Use of defines as constants
#define NEWWEAPONNAME "chainsaw with lasersight"
string s;
s = NEWWEAPONNAME; // Same as s = "chainsaw with lasersight";
s = #NEWWEAPONNAME; // Also same as s = "chainsaw with lasersight";
// Simple use of macros
#define ISEQUAL(a,b) (a == b)
float float1, float2;
if (float1 == float2)
   dosomething();
if (ISEQUAL(float1, float2)) // Does the same thing as the previous if
   dosomething(); 
// Use of stringify with macros
#define OBJECT(a) #a
string s;
s = OBJECT(mouse); // Same as s = "mouse";
// Use of concatenate with macros
#define SPECIALCLASS(a) float special_##a
SPECIALCLASS(thing); // same as float special_thing;

Warning: Macros are not the same as functions. For example:

float x;

#define SQRT(x) (x*x)
float squareroot (float x) { return x * x; }
float subtract2fromx (void) { x = x - 2; return x; }

void testfunction (void)
{
   x = 7; 
   y = squareroot(subtract2fromx()); // Results in (7-2) * (7-2) = 25

   x = 7;
   z = SQRT(subtract2fromx()); // Results in (7-2) * ((7-2)-2) = 15
}

#undef

Syntax: #undef <defname>

After statement parsing, <defname> is considered undefined. FTEQCC will no longer parse <defname> or #<defname> when it is encountered.

Control Logic

Preprocessor control logic statements allow flow of control over program compilation. Note that these statements can be nested.

#ifdef

Syntax: #ifdef <defname>
See also: #else, #endif

Includes all lines contained within the terminated #ifdef block for compilation if <defname> is a defined preprocessor define.

Examples:

#define SOMETHING
float x;
#ifdef SOMETHING
// Since SOMETHING is defined, this block gets compiled
x = 1;
#endif
// x = 1 at this point.
#ifdef SOMETHINGELSE
// This block does not get compiled since I did not define SOMETHINGELSE
x = 2;
#endif
// x does not change. x = 1 at this point.
// ifdef nesting example
#define SOMETHING
#define SOMETHINGELSE
#define SOMETHINGOTHER
float x;
#ifdef SOMETHING
x = 2;
   #ifdef SOMETHINGELSE
   x = 3;
      #ifdef SOMETHINGOTHER
      x = 4;
      // this endif terminates ifdef SOMETHINGOTHER
      #endif
   // this endif terminates ifdef SOMETHINGELSE
   #endif
// this endif terminates ifdef SOMETHING
#endif
// x = 4 at this point

#ifndef

Syntax: #ifndef <defname>
See also: #else, #endif

Includes all lines contained within the terminated #ifdef block for compilation if <defname> is not a defined preprocessor define.

Example:

#define SOMETHINGELSE
float x;
#ifndef SOMETHING
// Since SOMETHING is not defined, this block gets compiled
x = 3;
#endif
// x = 3 at this point.
#ifndef SOMETHINGELSE
// This block does not get compiled since SOMETHINGELSE is defined
x = 4;
#endif
// x does not change. x = 3 at this point.

#if

Syntax: #if <value>
See also: #else, #endif

Includes all lines contained within the terminated #if block for compilation if <value> is non-zero, otherwise falls through to block termination.

Example:

float x;
#if 1
// This block is compiled
x = 2;
#endif
// x = 2 at this point.
#if 0
// This block is not compiled
x = 3;
#endif
// x doesn't change. x = 2 at this point.

#else

Syntax: #else
See also: #endif

Terminates an #if, #ifdef, or #ifndef block. Includes all lines contained within the terminated #else block for compilation if the previous #ifdef, #ifndef, or #if condition fails.

Example:

float x;
// This condition always fails
#if 0 
// so this code block never gets compiled
x = 1;
#else
// but the code contained in this block will
x = 2;
#endif
// x = 2 at this point.

#endif

Syntax: #endif

Terminates an #if, #ifdef, #ifndef, or #else block.

Compiler Messages

#message

Syntax: #message <message>

Prints a message of <message> in FTEQCC's output.

#warning

Syntax: #warning <message>

Causes FTEQCC to send a warning in compilation containing the message <message>.

#error

Syntax: #error <message>

Causes FTEQCC to error in compilation with the message <message>.

Compilation

#include

Syntax: #include <file>

Includes <file> for compilation with FTEQCC.

#includelist

Syntax: #includelist
See also: #endlist

Includes all lines within the terminated #includelist block as files for compilation within FTEQCC.

Example:

#includelist
first.qc
second.qc
third.qc
#endlist
// FTEQCC will compile first.qc, second.qc, third.qc

#endlist

Syntax: #endlist

Terminates an #includelist block.

#eof

Syntax: #eof

Terminates FTEQCC parsing. No compilation or preprocessor parsing will be done after an #eof in the file.

Progs Control

#output

Depreciated, use #pragma PROGS_DAT instead.

#forcecrc

Syntax: #forcecrc <crc>

Forces the progs to compile with a specific CRC value instead of the precalculated one depending on target type.

#copyright

Depreciated, use #pragma COPYRIGHT instead.

#datafile

Syntax: #datafile <file>

Embeds <file> within the progs. Only available for FTE target type progs. FTEQW does not expand these embedded files within its' filesystem yet.

Pack (PAK) files

Although made obsolete by decent PAK editors and engines supporting other archive formats, FTEQCC still includes support for generating PAK files just as the original QCC did. FTEQCC also has support for precompiler statements for creating PAK files to avoid wasting statements within the QuakeC code itself. Note that the pack statements have no effect unless FTEQCC is passed the parameters required to generate PAK files.

#packid

Syntax: #packid <id>

Selects <id> as the current pack id.

#pack

Syntax: #pack <file>
See also: #packid

Groups <file> with the previous #packid.

Example:

#packid 0
#pack "progs/rocket.mdl"
// Will generate pak0.pak containing progs/rocket.mdl

Pragma (#pragma)

#pragma is an extensive precompiler statement which controls many aspects of the compiler. Note that all unknown #pragma statements encountered by FTEQCC are ignored (with a warning.)

#pragma DONT_COMPILE_THIS_FILE

This pragma is parsed but ignored by FTEQCC so PREQCC-using code can compile cleanly.

#pragma COPYRIGHT

Syntax: #pragma COPYRIGHT <message>

Changes the string to be embedded at the end of a compiled progs. <message> is the message to embed.

#pragma TARGET

Syntax: #pragma TARGET <target>

Switches compiled progs to a specific target type.

<target> can be the following:

  • ID, STANDARD: standard Quake progs
  • KK7: kkqwsv progs
  • H2, HEXEN2: Hexen 2 progs
  • FTE: FTE progs
  • DEBUG, FTEDEBUG: FTE progs with debug information

It is not recommended to switch target types during compilation.

#pragma sourcefile

Syntax: #pragma sourcefile <nextsrc>

Instructs fteqcc that once the current .src file has been compiled and resulted in a .dat, the named .src file should be also be compiled.
It is not uncommon to have a single .src file with thre #pragma sourcefiles in for each module and nothing else. This is especially useful with fteqccgui, as it allows you to compile all 3 modules from the same gui instance, and this also simplifies debugging.

#pragma PROGS_SRC

This pragma is parsed but ignored by FTEQCC so PREQCC-using code can compile cleanly.

#pragma PROGS_DAT

Syntax: #pragma PROGS_DAT <progsfile>

Changes the destination file you wish to compile to. <progsfile> contains the new file name.

Example:

#ifdef MONSTERS
   #pragma PROGS_DAT monsters.dat
   #message FTEQCC will now compile to monsters.dat
#else
   #pragma PROGS_DAT nomonsters.dat
   #message FTEQCC will now compile to nomonsters.dat
#endif

#pragma keyword and #pragma flag

Syntax:

  • #pragma keyword <onoroff> <keywordid>
  • #pragma flag <onoroff> <keywordid>

Enables or disables a keyword or compiler flag matching <keywordid>. #pragma keyword and #pragma flag are functionally equal.

<onoroff> can be the following:

  • enable, on: enable the chosen keyword or compiler flag
  • disable, off: disable the chosen keyword or compiler flag

See FTEQCC Keywords for all of the possibilities of <keywordid>.

#pragma warning

Syntax: #pragma warning <onoroff> <warningid>

Enables or disables a compiler warning matching <warningid>.

<onoroff> can be the following:

  • enable, on: enable the chosen warning
  • disable, off: disable the chosen warning
  • error: makes the warning fatal
  • toggle: toggle the warning state

See FTEQCC Warnings and Errors for all of the possibilities of <warningid>.