public bool HandleIfDef( Token body, int line ) { if ( this.EnableOutput ) { this.Error( line, "Too many embedded #if directives", null ); return false; } var cpp = new GLSLESPreprocessor( body, line ); Token t = cpp.GetToken( false ); if ( t.Type != Token.Kind.Keyword ) { this.Error( line, "Expecting a macro name after #ifdef, got", t ); return false; } this.EnableOutput = false; //has to be set to false 32 times before this matters do { t = cpp.GetToken( false ); } while ( t.Type == Token.Kind.Whitespace || t.Type == Token.Kind.Comment || t.Type == Token.Kind.Linecomment ); if ( t.Type != Token.Kind.EOS ) { this.Error( line, "Warning: Ignoring garbage after directive", t ); } return true; }
protected override void LoadFromSource() { var cpp = new GLSLESPreprocessor(); //Pass all user-defined macros to preprocessor if ( this.preprocessorDefines.Length > 0 ) { int pos = 0; while ( pos != this.preprocessorDefines.Length ) { //Find delims int endpos = this.preprocessorDefines.IndexOf( ";,=", pos ); if ( endpos != -1 ) { int macroNameStart = pos; int macroNameLen = endpos - pos; pos = endpos; //Check definition part if ( this.preprocessorDefines[ pos ] == '=' ) { //Set up a definition, skip delim ++pos; int macroValStart = pos; int macroValLen; endpos = this.preprocessorDefines.IndexOf( ";,", pos ); if ( endpos == -1 ) { macroValLen = this.preprocessorDefines.Length - pos; pos = endpos; } else { macroValLen = endpos - pos; pos = endpos + 1; } cpp.Define( this.preprocessorDefines + macroNameStart, macroNameLen, this.preprocessorDefines + macroValStart, macroValLen ); } else { //No definition part, define as "1" ++pos; cpp.Define( this.preprocessorDefines + macroNameStart, macroNameLen, 1 ); } } else { pos = endpos; } } int outSize = 0; string src = source; int srcLen = source.Length; string outVal = cpp.Parse( src, srcLen, out outSize ); if ( outVal == null || outSize == 0 ) { //Failed to preprocess, break out throw new AxiomException( "Failed to preprocess shader " + base.Name ); } source = new string( outVal.ToCharArray(), 0, outSize ); } }
public bool HandleUnDef( Token body, int line ) { var cpp = new GLSLESPreprocessor( body, line ); Token t = cpp.GetToken( false ); if ( t.Type != Token.Kind.Keyword ) { this.Error( line, "Expecting a macro name after #undef, got", t ); return false; } //Don't barf if macro does not exist = standard C behavior this.Undef( t.String, t.Length ); do { t = cpp.GetToken( false ); } while ( t.Type == Token.Kind.Whitespace || t.Type == Token.Kind.Comment || t.Type == Token.Kind.Linecomment ); if ( t.Type != Token.Kind.EOS ) { this.Error( line, "Warning: Ignoring garbage after directive", t ); } return true; }
public bool HandleDefine( Token body, int line ) { var cpp = new GLSLESPreprocessor( body, line ); Token t = cpp.GetToken( false ); if ( t.Type != Token.Kind.Keyword ) { this.Error( line, "Macro name expected after #define", null ); return false; } var m = new Macro( t ); m.Body = body; t = cpp.GetArguments( m.NumArgs, m.Args, false ); while ( t.Type == Token.Kind.Whitespace ) { t = cpp.GetToken( false ); } switch ( t.Type ) { case Token.Kind.Newline: case Token.Kind.EOS: //Assing "" to token t = new Token( Token.Kind.Text, string.Empty, 0 ); break; case Token.Kind.Error: m = null; return false; default: t.Type = Token.Kind.Text; t.Length = cpp.SourceEnd - t.String.Length; break; } m.Value = t; m.Next = this.MacroList; this.MacroList = m; return true; }
public Token Expand( int numArgs, Token[] args, Macro macros ) { this.Expanding = true; var cpp = new GLSLESPreprocessor(); cpp.MacroList = macros; //Define a new macro for every argument int i; for ( i = 0; i < numArgs; i++ ) { cpp.Define( this.Args[ i ].String, this.Args[ i ].Length, args[ i ].String, args[ i ].Length ); } //The rest arguments are empty for ( ; i < this.NumArgs; i++ ) { cpp.Define( this.Args[ i ].String, this.Args[ i ].Length, string.Empty, 0 ); } //Now run the macro expansion through the supplimentary preprocessor Token xt = cpp.Parse( this.Value ); this.Expanding = false; //Remove the extra macros we have defined for ( i = this.NumArgs - 1; i >= 0; i-- ) { cpp.Undef( this.Args[ i ].String, this.Args[ i ].Length ); } cpp.MacroList = null; return xt; }
public static Token ExpandDefined( GLSLESPreprocessor parent, int numArgs, Token[] args ) { if ( numArgs != 1 ) { parent.Error( parent.Line, "The defined() function takes exactly one argument", null ); return new Token( Token.Kind.Error ); } string v = ( parent.IsDefined( args[ 0 ] ) != null ) ? "1" : "0"; return new Token( Token.Kind.Number, v, 1 ); }
public bool GetValue( Token token, out long value, int line ) { value = 0; Token r; Token vt = token; if ( ( vt.Type == Token.Kind.Keyword || vt.Type == Token.Kind.Text || vt.Type == Token.Kind.Number ) && ( vt.String == string.Empty || vt.String == null ) ) { this.Error( line, "Trying to evaluate an empty expression", null ); return false; } if ( vt.Type == Token.Kind.Text ) { var cpp = new GLSLESPreprocessor( token, line ); cpp.MacroList = this.MacroList; Token t = cpp.GetExpression( out r, line, 0 ); cpp.MacroList = null; if ( t.Type == Token.Kind.Error ) { return false; } if ( t.Type != Token.Kind.EOS ) { this.Error( line, "Garbage afer expression", t ); return false; } vt = r; } Macro m; switch ( vt.Type ) { case Token.Kind.EOS: case Token.Kind.Error: return false; case Token.Kind.Text: case Token.Kind.Number: if ( !vt.GetValue( out value ) ) { this.Error( line, "Not a numeric expression", vt ); return false; } break; case Token.Kind.Keyword: //Try to expand the macro m = this.IsDefined( vt ); if ( m != null && !m.Expanding ) { Token x = this.ExpandMacro( vt ); m.Expanding = true; bool rc = this.GetValue( x, out value, line ); m.Expanding = false; return rc; } //Undefined macro, "expand to 0 mimic cpp behaviour value = 0; break; default: this.Error( line, "Unexpected token", vt ); break; } return true; }