@@ -10,6 +10,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
1010
1111</editor-fold> */
1212
13+ #include < vsg/core/Exception.h>
1314#include < vsg/core/Version.h>
1415#include < vsg/io/Logger.h>
1516#include < vsg/io/Options.h>
@@ -30,6 +31,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
3031#endif
3132
3233#include < algorithm>
34+ #include < cassert>
3335#include < iomanip>
3436
3537#ifndef VK_API_VERSION_MAJOR
@@ -444,7 +446,8 @@ std::string ShaderCompiler::combineSourceAndDefines(const std::string& source, c
444446 return str.substr (start + 1 , (end - start) - 1 );
445447 };
446448
447- auto split = [](const std::string& str, const char & separator) {
449+ // returns the string split into sanitized tokens
450+ auto split = [&sanitise](const std::string& str, const char & separator) {
448451 std::vector<std::string> elements;
449452
450453 std::string::size_type prev_pos = 0 , pos = 0 ;
@@ -453,10 +456,12 @@ std::string ShaderCompiler::combineSourceAndDefines(const std::string& source, c
453456 {
454457 auto substring = str.substr (prev_pos, pos - prev_pos);
455458 elements.push_back (substring);
459+ sanitise (elements.back ());
456460 prev_pos = ++pos;
457461 }
458462
459463 elements.push_back (str.substr (prev_pos, pos - prev_pos));
464+ sanitise (elements.back ());
460465
461466 return elements;
462467 };
@@ -465,6 +470,31 @@ std::string ShaderCompiler::combineSourceAndDefines(const std::string& source, c
465470 ss << line << " \n " ;
466471 };
467472
473+ /*
474+ * Verify that all the shader compiler defines are of the form "name" or "name=value" and that
475+ * the set doesn't contain entries with the same name and different values. This check is only
476+ * a temporary stopgap until the shader compiler defines container is updated from a
477+ * std::set<std::string>, to a std::map<std::string,std::string> to more properly manage defines
478+ * with optional values.
479+ */
480+ std::set<std::string> uniqueDefines;
481+ for (auto nameValueDef : defines)
482+ {
483+ auto nameValueDefElems = split (nameValueDef, ' =' );
484+ // simple check for formatting issues
485+ if (nameValueDefElems.size () != 1 && nameValueDefElems.size () != 2 )
486+ {
487+ throw Exception{" Error: Incorrectly formatted shader compile define. Acceptable formats are either a name or name=value." };
488+ }
489+ // verify that a valueless define or a name=value define with the same name has not already been encountered
490+ if (uniqueDefines.count (nameValueDefElems.front ()) != 0 )
491+ {
492+ throw Exception{" Error: Found two shader compiler defines with the same name and different values." };
493+ }
494+ // keep track that we have seen this define name
495+ uniqueDefines.insert (nameValueDefElems.front ());
496+ }
497+
468498 std::istringstream iss (source);
469499 std::ostringstream headerstream;
470500 std::ostringstream sourcestream;
@@ -493,16 +523,20 @@ std::string ShaderCompiler::combineSourceAndDefines(const std::string& source, c
493523
494524 addLine (headerstream, line);
495525
496- // loop the imported defines and see if it's also requested in defines, if so insert a define line
497- for (auto importedDef : importedDefines )
526+ // loop over the requested defines and see if it's also in the imported defines, if so insert a define line
527+ for (auto nameValueDef : defines )
498528 {
499- auto sanitiesedImportDef = importedDef;
500- sanitise (sanitiesedImportDef);
529+ // separate the define name from its optional value
530+ auto nameValueDefElems = split (nameValueDef, ' =' );
531+ assert (nameValueDefElems.size () == 1 || nameValueDefElems.size () == 2 );
501532
502- auto finditr = std::find (defines .begin (), defines .end (), sanitiesedImportDef );
533+ auto finditr = std::find (importedDefines .begin (), importedDefines .end (), nameValueDefElems. front () );
503534 if (finditr != defines.end ())
504535 {
505- addLine (headerstream, " #define " + sanitiesedImportDef);
536+ // output the pre-processor define directive with its name and optional value
537+ addLine (headerstream, " #define " + nameValueDefElems.front () +
538+ (nameValueDefElems.size () == 2
539+ ? " " +nameValueDefElems.back () : std::string ()));
506540 }
507541 }
508542 }
0 commit comments