/*========================================================================= Program: Visualization Toolkit Module: vtkParsePreprocess.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /*------------------------------------------------------------------------- Copyright (c) 2010 David Gobbi. Contributed to the VisualizationToolkit by the author in June 2010 under the terms of the Visualization Toolkit 2008 copyright. -------------------------------------------------------------------------*/ /** This file provides subroutines to assist in preprocessing C/C++ header files. It evaluates preprocessor directives and stores a list of all preprocessor macros. The preprocessing is done in-line while the file is being parsed. Macros that are defined in the file are stored but are not automatically expanded. The parser can query the macro definitions, expand them into plain text, or ask the preprocessor to evaluate them and return an integer result. The typical usage of this preprocessor is that the main parser will pass any lines that begin with '#' to the vtkParsePreprocess_HandleDirective() function, which will evaluate the line and provide a return code. The return code will tell the main parser if a syntax error or macro lookup error occurred, and will also let the parser know if an #if or #else directive requires that the next block of code be skipped. */ #ifndef vtkParsePreprocess_h #define vtkParsePreprocess_h #include "vtkParseString.h" /** * The preprocessor int type. Use the compiler's longest int type. */ #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) typedef __int64 preproc_int_t; typedef unsigned __int64 preproc_uint_t; #else typedef long long preproc_int_t; typedef unsigned long long preproc_uint_t; #endif /** * Struct to describe a preprocessor symbol. */ typedef struct _MacroInfo { const char *Name; const char *Definition; const char *Comment; /* unused */ int NumberOfParameters; /* only if IsFunction == 1 */ const char **Parameters; /* symbols for parameters */ int IsFunction; /* this macro requires arguments */ int IsVariadic; /* this macro can take unlimited arguments */ int IsExternal; /* this macro is from an included file */ int IsExcluded; /* do not expand this macro */ } MacroInfo; /** * Contains all symbols defined thus far (including those defined * in any included header files). */ typedef struct _PreprocessInfo { const char *FileName; /* the file that is being parsed */ MacroInfo ***MacroHashTable; /* hash table for macro lookup */ int NumberOfIncludeDirectories; const char **IncludeDirectories; int NumberOfIncludeFiles; /* all included files */ const char **IncludeFiles; StringCache *Strings; /* to aid string allocation */ int IsExternal; /* label all macros as "external" */ int ConditionalDepth; /* internal state variable */ int ConditionalDone; /* internal state variable */ } PreprocessInfo; /** * Platforms. Always choose native unless crosscompiling. */ enum _preproc_platform_t { VTK_PARSE_NATIVE = 0 }; /** * Directive return values. */ enum _preproc_return_t { VTK_PARSE_OK = 0, VTK_PARSE_SKIP = 1, /* skip next block */ VTK_PARSE_PREPROC_DOUBLE = 2, /* encountered a double */ VTK_PARSE_PREPROC_FLOAT = 3, /* encountered a float */ VTK_PARSE_PREPROC_STRING = 4, /* encountered a string */ VTK_PARSE_MACRO_UNDEFINED = 5, /* macro lookup failed */ VTK_PARSE_MACRO_REDEFINED = 6, /* attempt to redefine a macro */ VTK_PARSE_FILE_NOT_FOUND = 7, /* include file not found */ VTK_PARSE_FILE_OPEN_ERROR = 8, /* include file not readable */ VTK_PARSE_FILE_READ_ERROR = 9, /* error during read */ VTK_PARSE_MACRO_NUMARGS = 10, /* wrong number of args to func macro */ VTK_PARSE_SYNTAX_ERROR = 11, /* any and all syntax errors */ VTK_PARSE_OUT_OF_MEMORY = 12 /* out-of-memory */ }; /** * Bitfield for fatal errors. */ #define VTK_PARSE_FATAL_ERROR 0xF8 #ifdef __cplusplus extern "C" { #endif /** * Handle a preprocessor directive. Return value VTK_PARSE_OK * means that no errors occurred, while VTK_PARSE_SKIP means that * a conditional directive was encountered and the next code * block should be skipped. The preprocessor has an internal state * machine that keeps track of conditional if/else/endif directives. * All other return values indicate errors, and it is up to the * parser to decide which errors are fatal. The preprocessor * only considers syntax errors and I/O errors to be fatal. */ int vtkParsePreprocess_HandleDirective( PreprocessInfo *info, const char *directive); /** * Evaluate a preprocessor expression, providing an integer result * in "val", and whether it is unsigned in "is_unsigned". A return * value of VTK_PARSE_OK means that no errors occurred, while * VTK_PREPROC_DOUBLE, VTK_PREPROC_FLOAT, and VTK_PREPROC_STRING * indicate that the preprocessor encountered a non-integer value. * Error return values are VTK_PARSE_MACRO_UNDEFINED and * VTK_PARSE_SYNTAX_ERRORS. Undefined macros evaluate to zero. */ int vtkParsePreprocess_EvaluateExpression( PreprocessInfo *info, const char *text, preproc_int_t *val, int *is_unsigned); /** * Add all standard preprocessor symbols. Use VTK_PARSE_NATIVE * as the platform. In the future, other platform specifiers * might be added to allow crosscompiling. */ void vtkParsePreprocess_AddStandardMacros( PreprocessInfo *info, int platform); /** * Add a preprocessor symbol, including a definition. Return * values are VTK_PARSE_OK and VTK_PARSE_MACRO_REDEFINED. */ int vtkParsePreprocess_AddMacro( PreprocessInfo *info, const char *name, const char *definition); /** * Remove a preprocessor symbol. Return values are VTK_PARSE_OK * and VTK_PARSE_MACRO_UNDEFINED. */ int vtkParsePreprocess_RemoveMacro( PreprocessInfo *info, const char *name); /** * Return a preprocessor symbol struct, or NULL if not found. */ MacroInfo *vtkParsePreprocess_GetMacro( PreprocessInfo *info, const char *name); /** * Expand a macro. A function macro must be given an argstring * with args in parentheses, otherwise the argstring can be NULL. * returns NULL if the wrong number of arguments were given. */ const char *vtkParsePreprocess_ExpandMacro( PreprocessInfo *info, MacroInfo *macro, const char *argstring); /** * Free an expanded macro */ void vtkParsePreprocess_FreeMacroExpansion( PreprocessInfo *info, MacroInfo *macro, const char *text); /** * Fully process a string with the preprocessor, and * return a new string or NULL if a fatal error occurred. */ const char *vtkParsePreprocess_ProcessString( PreprocessInfo *info, const char *text); /** * Free a processed string. Only call this method if * the string returned by ProcessString is different from * the original string, because ProcessString will just * return the original string if no processing was needed. */ void vtkParsePreprocess_FreeProcessedString( PreprocessInfo *info, const char *text); /** * Add an include directory. The directories that were added * first will be searched first. */ void vtkParsePreprocess_IncludeDirectory( PreprocessInfo *info, const char *name); /** * Find an include file in the path. If system_first is set, then * the current directory is ignored unless it is explicitly in the * path. A null return value indicates that the file was not found. * If already_loaded is set, then the file was already loaded. This * preprocessor never loads the same file twice. */ const char *vtkParsePreprocess_FindIncludeFile( PreprocessInfo *info, const char *filename, int system_first, int *already_loaded); /** * Initialize a preprocessor symbol struct. */ void vtkParsePreprocess_InitMacro(MacroInfo *symbol); /** * Free a preprocessor macro struct */ void vtkParsePreprocess_FreeMacro(MacroInfo *macro); /** * Initialize a preprocessor struct. */ void vtkParsePreprocess_Init( PreprocessInfo *info, const char *filename); /** * Free a preprocessor struct and its contents; */ void vtkParsePreprocess_Free(PreprocessInfo *info); #ifdef __cplusplus } /* extern "C" */ #endif #endif