Skip to content

Commit b48b6a4

Browse files
committed
CPreprocessor: add passthrough support for #if direcrtives
1 parent 37b6fb7 commit b48b6a4

File tree

4 files changed

+69
-9
lines changed

4 files changed

+69
-9
lines changed

RenderSystems/GLSupport/include/GLSL/OgreGLSLPreprocessor.h

+12
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,13 @@ namespace Ogre {
207207
/// A stack of 32 booleans packed into one value :)
208208
unsigned EnableOutput;
209209
unsigned EnableElif;
210+
unsigned Passthrough;
210211
/// The list of macros defined so far
211212
std::forward_list<Macro> MacroList;
212213

214+
/// List of define prefixes to pass through
215+
std::vector<const char*> PassthroughList;
216+
213217
/**
214218
* Private constructor to re-parse a single token.
215219
*/
@@ -444,6 +448,14 @@ namespace Ogre {
444448
/// Destroy the preprocessor object
445449
virtual ~CPreprocessor ();
446450

451+
/** Define-prefixes from this list cause the #if directive not to be expanded
452+
453+
useful to test GLSL extension support at runtime
454+
@param lst the list. Supposed to contain string literals. Make sure that the memory pointed
455+
is available throughout the lifetime of CPreprocessor otherwise.
456+
*/
457+
void setPassthroughDefines(const std::vector<const char*>& lst) { PassthroughList = lst; }
458+
447459
/**
448460
* Define a macro without parameters.
449461
* @param iMacroName

RenderSystems/GLSupport/src/GLSL/OgreGLSLPreprocessor.cpp

+39-8
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,7 @@ namespace Ogre {
989989

990990
EnableElif <<= 1;
991991
EnableOutput <<= 1;
992+
Passthrough <<= 1;
992993
if (val)
993994
EnableOutput |= 1;
994995
else
@@ -1118,6 +1119,22 @@ namespace Ogre {
11181119
return true;
11191120
}
11201121

1122+
static const char* strnstr(const char* haystack, size_t length, const char* needle)
1123+
{
1124+
size_t needle_length = strlen(needle);
1125+
for (size_t i = 0; i < length; i++)
1126+
{
1127+
if (i + needle_length > length)
1128+
{
1129+
return NULL;
1130+
}
1131+
if (strncmp(&haystack[i], needle, needle_length) == 0)
1132+
{
1133+
return &haystack[i];
1134+
}
1135+
}
1136+
return NULL;
1137+
}
11211138

11221139
CPreprocessor::Token CPreprocessor::HandleDirective (Token &iToken, int iLine)
11231140
{
@@ -1181,16 +1198,30 @@ namespace Ogre {
11811198
#define IS_DIRECTIVE(s) \
11821199
(dirlen == strlen(s) && (strncmp (directive, s, dirlen) == 0))
11831200

1201+
if (strncmp(directive, "if", 2) == 0)
1202+
{
1203+
for(auto e : PassthroughList)
1204+
{
1205+
if(strnstr(t.String, t.Length, e))
1206+
{
1207+
Passthrough |= 1;
1208+
printf("%s\n", String(t.String, t.Length).c_str());
1209+
}
1210+
}
1211+
}
1212+
1213+
bool passthrough = Passthrough & 1;
1214+
11841215
bool outputEnabled = ((EnableOutput & (EnableOutput + 1)) == 0);
11851216
bool rc;
11861217

11871218
if (IS_DIRECTIVE ("define") && outputEnabled)
11881219
rc = HandleDefine (t, iLine);
11891220
else if (IS_DIRECTIVE ("undef") && outputEnabled)
11901221
rc = HandleUnDef (t, iLine);
1191-
else if (IS_DIRECTIVE ("ifdef"))
1222+
else if (IS_DIRECTIVE ("ifdef") && !passthrough)
11921223
rc = HandleIfDef (t, iLine);
1193-
else if (IS_DIRECTIVE ("ifndef"))
1224+
else if (IS_DIRECTIVE ("ifndef") && !passthrough)
11941225
{
11951226
rc = HandleIfDef (t, iLine);
11961227
if (rc)
@@ -1199,19 +1230,18 @@ namespace Ogre {
11991230
EnableElif ^= 1;
12001231
}
12011232
}
1202-
else if (IS_DIRECTIVE ("if"))
1233+
else if (IS_DIRECTIVE ("if") && !passthrough)
12031234
rc = HandleIf (t, iLine);
1204-
else if (IS_DIRECTIVE ("elif"))
1235+
else if (IS_DIRECTIVE ("elif") && !passthrough)
12051236
rc = HandleElif (t, iLine);
12061237

1207-
else if (IS_DIRECTIVE ("else"))
1238+
else if (IS_DIRECTIVE ("else") && !passthrough)
12081239
rc = HandleElse (t, iLine);
1209-
else if (IS_DIRECTIVE ("endif"))
1240+
else if (IS_DIRECTIVE ("endif") && !passthrough)
12101241
rc = HandleEndIf (t, iLine);
12111242
else
12121243
{
1213-
//Error (iLine, "Unknown preprocessor directive", &iToken);
1214-
//return Token (Token::TK_ERROR);
1244+
if(IS_DIRECTIVE ("endif")) Passthrough &= ~1;
12151245

12161246
// Unknown preprocessor directive, roll back and pass through
12171247
Line = old_line;
@@ -1272,6 +1302,7 @@ namespace Ogre {
12721302
BOL = true;
12731303
EnableOutput = 1;
12741304
EnableElif = 0;
1305+
Passthrough = 0;
12751306

12761307
// Accumulate output into this token
12771308
Token output (Token::TK_TEXT);

RenderSystems/GLSupport/src/GLSL/OgreGLSLShaderCommon.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ namespace Ogre {
5757
// Preprocess the GLSL shader in order to get a clean source
5858
CPreprocessor cpp;
5959

60+
cpp.setPassthroughDefines({"GL_ARB", "GL_EXT", "GL_OES", "__VERSION__"});
6061
// Define "predefined" macros.
61-
// TODO: decide, should we define __VERSION__, and with what value.
6262
if(getLanguage() == "glsles")
6363
cpp.Define("GL_ES", 5, 1);
6464

Tests/RenderSystems/GLSupport/GLSLTests.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,23 @@ TEST(CPreprocessorTests, MacroExpansion)
6161
free(out);
6262
}
6363

64+
TEST(CPreprocessorTests, Passthrough)
65+
{
66+
CPreprocessor prep;
67+
prep.setPassthroughDefines({"GL_ARB"});
68+
String src = "#ifdef GL_ARB_shader_texture_lod\n"
69+
"textureCubeLod\n"
70+
"#else\n"
71+
"textureCube\n"
72+
"#endif";
73+
74+
size_t olen;
75+
char* out = prep.Parse(src.c_str(), src.size(), olen);
76+
String str(out, olen);
77+
EXPECT_EQ(src, str);
78+
free(out);
79+
}
80+
6481
TEST(CPreprocessorTests, IfDef)
6582
{
6683
CPreprocessor prep;

0 commit comments

Comments
 (0)