- returns directives string and remaining source separately, so that parseTopLevel can start after the directives we've added - lineNumberStart indicates what value a #line directive should have after parsing #include statements
| 207 | // - returns directives string and remaining source separately, so that parseTopLevel can start after the directives we've added |
| 208 | // - lineNumberStart indicates what value a #line directive should have after parsing #include statements |
| 209 | void ShaderPreprocessor::parseDirectives( const std::string &source, const fs::path &sourcePath, std::string *directives, std::string *sourceBody, int *versionNumber, int *lineNumberStart ) |
| 210 | { |
| 211 | // go through each line and find the #version directive |
| 212 | int lineNumber = 1; |
| 213 | bool hasVersionLine = false; |
| 214 | |
| 215 | for( size_t lineStartPos = 0; lineStartPos < source.size(); /* */ ) { |
| 216 | size_t lineEndPos = source.find( '\n', lineStartPos ); |
| 217 | if( lineEndPos == std::string::npos ) |
| 218 | break; |
| 219 | |
| 220 | if( findVersionStatement( source.c_str() + lineStartPos, versionNumber ) ) { |
| 221 | // if no defines, return leaving the directive and sourceBody strings empty, |
| 222 | // thereby indicating to use the original source without modification; |
| 223 | if( mDefineDirectives.empty() ) { |
| 224 | *lineNumberStart = 1; |
| 225 | return; |
| 226 | } |
| 227 | |
| 228 | // Copy #version line and everything before it to the directives string, the rest to sourceBody |
| 229 | *directives = source.substr( 0, lineEndPos + 1 ); |
| 230 | *sourceBody = source.substr( lineEndPos + 1 ); |
| 231 | *lineNumberStart = lineNumber; |
| 232 | hasVersionLine = true; |
| 233 | |
| 234 | break; |
| 235 | } |
| 236 | |
| 237 | lineStartPos = lineEndPos + 1; |
| 238 | lineNumber++; |
| 239 | } |
| 240 | |
| 241 | // if we don't have a version yet, add a default one that will be at the top |
| 242 | if( ! hasVersionLine ) { |
| 243 | #if defined( CINDER_GL_ES_3 ) |
| 244 | *directives += "#version " + to_string( mVersion ) + " es\n"; |
| 245 | #else |
| 246 | *directives += "#version " + to_string( mVersion ) + "\n"; |
| 247 | #endif |
| 248 | |
| 249 | *sourceBody = source; // sourceBody is the entire source |
| 250 | *lineNumberStart = 0; |
| 251 | *versionNumber = mVersion; |
| 252 | } |
| 253 | |
| 254 | // append any #defines to the directives string |
| 255 | for( const auto &define : mDefineDirectives ) { |
| 256 | *directives += "#define " + define.first; |
| 257 | if( ! define.second.empty() ) |
| 258 | *directives += " " + define.second; |
| 259 | |
| 260 | *directives += "\n"; |
| 261 | } |
| 262 | |
| 263 | // if we've made any modifications, add a #line directive to ensure debug error statements are correct. |
| 264 | if( ! mDefineDirectives.empty() || ! hasVersionLine ) { |
| 265 | *directives += getLineDirective( sourcePath, *lineNumberStart, 0, *versionNumber ); |
| 266 | *lineNumberStart += 1; |