ezEngine  Release 25.03
ezPreprocessor Class Reference

ezPreprocessor implements a standard C preprocessor. It can be used to pre-process files to get the output after macro expansion and #ifdef handling. More...

#include <Preprocessor.h>

Classes

struct  ProcessingEvent
 The event data that the processor broadcasts. More...
 

Public Types

enum  IncludeType { MainFile, RelativeInclude, GlobalInclude }
 Describes the type of #include that was encountered during preprocessing. More...
 
using FileOpenCB = ezDelegate< ezResult(ezStringView, ezDynamicArray< ezUInt8 > &, ezTimestamp &)>
 This type of callback is used to read an #include file. sAbsoluteFile is the path that the FileLocatorCB reported, the result needs to be stored in FileContent.
 
using FileLocatorCB = ezDelegate< ezResult(ezStringView, ezStringView, IncludeType, ezStringBuilder &)>
 This type of callback is used to retrieve the absolute path of the sIncludeFile when #included inside sCurAbsoluteFile. More...
 
using PassThroughUnknownCmdCB = ezDelegate< bool(ezStringView)>
 Every time an unknown command (e.g. '#version') is encountered, this callback is used to determine whether the command shall be passed through. More...
 
using MacroParameters = ezDeque< ezTokenParseUtils::TokenStream >
 

Public Member Functions

void SetLogInterface (ezLogInterface *pLog)
 All error output is sent to the given ezLogInterface. More...
 
void SetCustomFileCache (ezTokenizedFileCache *pFileCache=nullptr)
 Allows to specify a custom cache object that should be used for storing the tokenized result of files. More...
 
void SetPassThroughPragma (bool bPassThrough)
 If set to true, all #pragma commands are passed through to the output, otherwise they are removed.
 
void SetPassThroughLine (bool bPassThrough)
 If set to true, all #line commands are passed through to the output, otherwise they are removed.
 
void SetImplicitPragmaOnce (bool bEnable)
 If set to true, all files are treated as if they contain a '#pragma once' directive, ie they will never be #included twice.
 
void SetPassThroughUnknownCmdsCB (PassThroughUnknownCmdCB callback)
 Sets the callback that is used to determine whether an unknown command is passed through or triggers an error.
 
void SetFileOpenFunction (FileOpenCB openAbsFileCB)
 Sets the callback that is needed to read input data. More...
 
void SetFileLocatorFunction (FileLocatorCB locateAbsFileCB)
 Sets the callback that is needed to locate an input file. More...
 
ezResult AddCustomDefine (ezStringView sDefinition)
 Adds a #define to the preprocessor, even before any file is processed. More...
 
ezResult Process (ezStringView sMainFile, ezTokenParseUtils::TokenStream &ref_tokenOutput)
 Processes the given file and returns the result as a stream of tokens. More...
 
ezResult Process (ezStringView sMainFile, ezStringBuilder &ref_sOutput, bool bKeepComments=true, bool bRemoveRedundantWhitespace=false, bool bInsertLine=false)
 Processes the given file and returns the result as a string. More...
 

Static Public Member Functions

static ezResult DefaultFileLocator (ezStringView sCurAbsoluteFile, ezStringView sIncludeFile, ezPreprocessor::IncludeType incType, ezStringBuilder &out_sAbsoluteFilePath)
 
static ezResult DefaultFileOpen (ezStringView sAbsoluteFile, ezDynamicArray< ezUInt8 > &ref_fileContent, ezTimestamp &out_fileModification)
 

Public Attributes

ezEvent< const ProcessingEvent & > m_ProcessingEvents
 Broadcasts events during the processing. This can be used to create detailed callstacks when an error is encountered. It also broadcasts errors and warnings with more detailed information than the log interface allows.
 

Detailed Description

ezPreprocessor implements a standard C preprocessor. It can be used to pre-process files to get the output after macro expansion and #ifdef handling.

For a detailed documentation about the C preprocessor, see https://gcc.gnu.org/onlinedocs/cpp/

This class implements all standard features:

  • object and function macros
  • Full evaluation of #if, #ifdef etc. including mathematical operations such as #if A > 42
  • Parameter stringification
  • Parameter concatenation
  • LINE and FILE macros
  • Fully correct #line evaluation for error output
  • Correct handling of VA_ARGS
  • #include handling
  • #pragma once
  • #warning and #error for custom failure messages

Member Typedef Documentation

◆ FileLocatorCB

This type of callback is used to retrieve the absolute path of the sIncludeFile when #included inside sCurAbsoluteFile.

Note that you should ensure that out_sAbsoluteFilePath is always identical (including casing and path slashes) when it is supposed to point to the same file, as this exact name is used for file lookup (and therefore also file caching). If it is not identical, file caching will not work, and on different OSes the file may be found or not.

◆ PassThroughUnknownCmdCB

Every time an unknown command (e.g. '#version') is encountered, this callback is used to determine whether the command shall be passed through.

If the callback returns false, an error is generated and parsing fails. The callback thus acts as a whitelist for all commands that shall be passed through.

Member Enumeration Documentation

◆ IncludeType

Describes the type of #include that was encountered during preprocessing.

Enumerator
MainFile 

This is used for the very first access to the main source file.

RelativeInclude 

An #include "file" has been encountered.

GlobalInclude 

An #include <file> has been encountered.

Member Function Documentation

◆ AddCustomDefine()

ezResult ezPreprocessor::AddCustomDefine ( ezStringView  sDefinition)

Adds a #define to the preprocessor, even before any file is processed.

This allows to have global macros that are always defined for all processed files, such as the current platform etc. sDefinition must be in the form of the text that follows a #define statement. So to define the macro "WIN32", just pass that string. You can define any macro that could also be defined in the source files.

If the definition is invalid, EZ_FAILURE is returned. Also the preprocessor might end up in an invalid state, so using it any further might fail (including crashing).

◆ Process() [1/2]

ezResult ezPreprocessor::Process ( ezStringView  sMainFile,
ezStringBuilder ref_sOutput,
bool  bKeepComments = true,
bool  bRemoveRedundantWhitespace = false,
bool  bInsertLine = false 
)

Processes the given file and returns the result as a string.

This function creates a string from the tokenized result. If bKeepComments is true, all block and line comments are included in the output string, otherwise they are removed.

◆ Process() [2/2]

ezResult ezPreprocessor::Process ( ezStringView  sMainFile,
ezTokenParseUtils::TokenStream ref_tokenOutput 
)

Processes the given file and returns the result as a stream of tokens.

This function is useful when you want to further process the output afterwards and thus need it in a tokenized form anyway.

◆ SetCustomFileCache()

void ezPreprocessor::SetCustomFileCache ( ezTokenizedFileCache pFileCache = nullptr)

Allows to specify a custom cache object that should be used for storing the tokenized result of files.

This allows to share one cache across multiple instances of ezPreprocessor and across time. E.g. it makes it possible to prevent having to read and tokenize include files that are referenced often.

◆ SetFileLocatorFunction()

void ezPreprocessor::SetFileLocatorFunction ( FileLocatorCB  locateAbsFileCB)

Sets the callback that is needed to locate an input file.

The default file locator will assume that the main source file and all files #included in angle brackets can be opened without modification. Files #included in "" will be appended as relative paths to the path of the file they appeared in.

◆ SetFileOpenFunction()

void ezPreprocessor::SetFileOpenFunction ( FileOpenCB  openAbsFileCB)

Sets the callback that is needed to read input data.

The default file open function will just try to open files via ezFileReader.

◆ SetLogInterface()

void ezPreprocessor::SetLogInterface ( ezLogInterface pLog)

All error output is sent to the given ezLogInterface.

Note that when the preprocessor encounters any error, it will stop immediately and usually no output is generated. However, there are also a few cases where only a warning is generated, in this case preprocessing will continue without problems.

Additionally errors and warnings are also broadcast through m_ProcessingEvents. So if you want to output more detailed information, that method should be preferred, because the events carry more information about the current file and line number etc.


The documentation for this class was generated from the following files: