private bool ScanPreProcessorDirective(bool insideExcludedBlock, int nonExcludedEndifCount){ bool exclude = insideExcludedBlock; int savedStartPos = this.startPos; int i = this.startPos-1; while (i > 0 && Scanner.IsBlankSpace(this.GetChar(i))){ i--; } if (i > 0 && !this.IsLineTerminator(this.GetChar(i), 0)){ this.HandleError(Error.BadDirectivePlacement); goto skipToEndOfLine; } this.SkipBlanks(); //Check EOL/EOF? this.startPos = this.endPos-1; this.ScanIdentifier(); switch (this.GetIdentifierString()){ case "define": if (insideExcludedBlock) goto skipToEndOfLine; if (!this.allowPPDefinitions){ this.HandleError(Error.PPDefFollowsToken); goto skipToEndOfLine; } this.startPos = this.endPos; char chr = this.SkipBlanks(); if (this.IsEndLineOrEOF(chr, 0)){ this.HandleError(Error.ExpectedIdentifier); break; } this.identifier.Length = 0; this.endPos--; this.startPos = this.endPos; if (!this.IsIdentifierStartChar(chr)) this.HandleError(Error.ExpectedIdentifier); else{ this.ScanIdentifier(); if (this.PreprocessorDefinedSymbols == null){ this.PreprocessorDefinedSymbols = new Hashtable(); this.PreprocessorDefinedSymbols["true"] = "true"; } string s = this.GetIdentifierString(); if (s == "true" || s == "false" || !this.IsIdentifierStartChar(s[0])){ this.HandleError(Error.ExpectedIdentifier); goto skipToEndOfLine; }else this.PreprocessorDefinedSymbols[s] = s; } break; case "undef": if (insideExcludedBlock) goto skipToEndOfLine; if (!this.allowPPDefinitions){ this.HandleError(Error.PPDefFollowsToken); goto skipToEndOfLine; } this.startPos = this.endPos; chr = this.SkipBlanks(); if (this.IsEndLineOrEOF(chr, 0)){ this.HandleError(Error.ExpectedIdentifier); break; } this.identifier.Length = 0; this.endPos--; this.startPos = this.endPos; if (!this.IsIdentifierStartChar(chr)) this.HandleError(Error.ExpectedIdentifier); else{ this.ScanIdentifier(); if (this.PreprocessorDefinedSymbols == null){ this.PreprocessorDefinedSymbols = new Hashtable(); this.PreprocessorDefinedSymbols["true"] = "true"; } string s = this.GetIdentifierString(); if (s == "true" || s == "false" || !this.IsIdentifierStartChar(s[0])){ this.HandleError(Error.ExpectedIdentifier); goto skipToEndOfLine; }else this.PreprocessorDefinedSymbols[s] = null; } break; case "if": if (insideExcludedBlock){ this.endIfCount++; this.RestartStateHasChanged = true; goto skipToEndOfLine; } char c = (char)0; exclude = !this.ScanPPExpression(ref c); if (this.sink != null) { if (this.regionCtxStack == null) this.regionCtxStack = new Stack(); SourceContext regionCtx = this.CurrentSourceContext; regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos); regionCtx.EndPos = regionCtx.StartPos; regionCtxStack.Push(regionCtx); } if (!exclude) this.includeCount++; this.endIfCount++; this.nonExcludedEndIfCount++; this.RestartStateHasChanged = true; if (this.IsEndLineOrEOF(c, 0)) return exclude; break; case "elif": if (insideExcludedBlock && (this.endIfCount - nonExcludedEndifCount) > 1) goto skipToEndOfLine; if (this.elseCount == this.endIfCount){ //Already found an else this.HandleError(Error.UnexpectedDirective); goto skipToEndOfLine; } c = (char)0; exclude = !this.ScanPPExpression(ref c); if (this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0) { SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop(); startRegionCtx.EndPos = this.PositionOfLastCharacterOfPreviousLine(savedStartPos)+1; if (startRegionCtx.EndPos > startRegionCtx.StartPos) this.sink.AddCollapsibleRegion(startRegionCtx, insideExcludedBlock); SourceContext regionCtx = this.CurrentSourceContext; regionCtx.StartPos = this.endPos; regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos); regionCtx.EndPos = regionCtx.StartPos; regionCtxStack.Push(regionCtx); } if (this.includeCount == this.endIfCount){ //The #if, or a preceding #elif has already been included, hence this block must be excluded regardless of the expression exclude = true; break; } if (!exclude){ this.includeCount++; this.RestartStateHasChanged = true; } if (this.IsEndLineOrEOF(c, 0)) return exclude; break; case "else": if (insideExcludedBlock && (this.endIfCount - nonExcludedEndifCount) > 1) goto skipToEndOfLine; if (this.elseCount == this.endIfCount){ this.HandleError(Error.UnexpectedDirective); goto skipToEndOfLine; } if (this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0) { SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop(); startRegionCtx.EndPos = this.PositionOfLastCharacterOfPreviousLine(savedStartPos)+1; if (startRegionCtx.EndPos > startRegionCtx.StartPos) this.sink.AddCollapsibleRegion(startRegionCtx, insideExcludedBlock); SourceContext regionCtx = this.CurrentSourceContext; regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos); regionCtx.EndPos = regionCtx.StartPos; regionCtxStack.Push(regionCtx); } this.elseCount++; this.RestartStateHasChanged = true; if (this.includeCount == this.endIfCount){ exclude = true; break; } exclude = false; this.includeCount++; break; case "endif": if (this.endIfCount <= 0){ this.endIfCount = 0; this.nonExcludedEndIfCount = 0; this.RestartStateHasChanged = true; this.HandleError(Error.UnexpectedDirective); goto skipToEndOfLine; } bool collapse = false; this.endIfCount--; if (!insideExcludedBlock || this.nonExcludedEndIfCount > this.endIfCount) this.nonExcludedEndIfCount--; if (this.includeCount > this.endIfCount){ //Can only happen if the #if-#else-#elif-#end block itself appears in an included block and has an included part this.includeCount = this.endIfCount; collapse = true; } if (this.endIfCount > 0) this.elseCount = this.endIfCount-1; else{ this.elseCount = 0; collapse = true; } if (collapse && this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0) { SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop(); startRegionCtx.EndPos = this.PositionOfLastCharacterOfPreviousLine(savedStartPos)+1; if (startRegionCtx.EndPos > startRegionCtx.StartPos) this.sink.AddCollapsibleRegion(startRegionCtx, insideExcludedBlock); if (this.regionCtxStack.Count == 0) this.regionCtxStack = null; } this.RestartStateHasChanged = true; break; case "line": if (insideExcludedBlock) goto skipToEndOfLine; c = this.SkipBlanks(); int lnum = -1; if ('0' <= c && c <= '9'){ this.startPos = --this.endPos; while ('0' <= (c = this.GetChar(++this.endPos)) && c <= '9'); try{ lnum = int.Parse(this.GetTokenSource(), CultureInfo.InvariantCulture); if (lnum <= 0){ this.startPos = this.endPos; this.HandleError(Error.InvalidLineNumber); goto skipToEndOfLine; }else if (this.IsEndLineOrEOF(c, 0)) goto setLineInfo; }catch(OverflowException){ this.startPos++; this.HandleError(Error.IntOverflow); goto skipToEndOfLine; } }else{ this.startPos = this.endPos-1; this.ScanIdentifier(); if (this.startPos != this.endPos-1){ string str = this.GetIdentifierString(); if (str == "default"){ this.document = this.originalDocument; break; } if (str == "hidden" && this.document != null){ this.document = new Document(this.document.Name, this.document.LineNumber, this.document.Text, this.document.DocumentType, this.document.Language, this.document.LanguageVendor); this.document.Hidden = true; break; } } this.HandleError(Error.InvalidLineNumber); goto skipToEndOfLine; } c = this.SkipBlanks(); this.startPos = this.endPos-1; if (c == '/'){ if (this.GetChar(this.endPos) == '/'){ this.endPos--; goto setLineInfo; }else{ this.startPos = this.endPos-1; this.HandleError(Error.EndOfPPLineExpected); goto skipToEndOfLine; } } if (c == '"'){ while ((c = this.GetChar(this.endPos++)) != '"' && !this.IsEndLineOrEOF(c, 0)); if (c != '"'){ this.HandleError(Error.MissingPPFile); goto skipToEndOfLine; } this.startPos++; this.endPos--; string filename = this.GetTokenSource(); this.endPos++; if (this.document != null) this.document = new Document(filename, 1, this.document.Text, this.document.DocumentType, this.document.Language, this.document.LanguageVendor); }else if (!this.IsEndLineOrEOF(c, 0)){ this.HandleError(Error.MissingPPFile); goto skipToEndOfLine; }else goto setLineInfo; c = this.SkipBlanks(); this.startPos = this.endPos-1; if (c == '/'){ if (this.GetChar(this.endPos) == '/'){ this.endPos--; goto setLineInfo; }else{ this.startPos = this.endPos-1; this.HandleError(Error.EndOfPPLineExpected); goto skipToEndOfLine; } } setLineInfo: Document doc = this.document; if (doc != null){ this.document = doc = new Document(doc.Name, 1, doc.Text, doc.DocumentType, doc.Language, doc.LanguageVendor); int offset = lnum - doc.GetLine(this.startPos); doc.LineNumber = offset; } if (this.IsEndLineOrEOF(c, 0)) return exclude; break; case "error": if (insideExcludedBlock) goto skipToEndOfLine; this.SkipBlanks(); this.startPos = --this.endPos; this.ScanString((char)0); this.HandleError(Error.ErrorDirective, this.unescapedString); break; case "warning": if (insideExcludedBlock) goto skipToEndOfLine; this.SkipBlanks(); this.startPos = --this.endPos; this.ScanString((char)0); this.HandleError(Error.WarningDirective, this.unescapedString); break; case "region": if (insideExcludedBlock) goto skipToEndOfLine; this.regionCount++; if (this.sink != null){ if (this.regionCtxStack == null) this.regionCtxStack = new Stack(); SourceContext regionCtx = this.CurrentSourceContext; regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos); regionCtx.StartPos = this.PositionOfLastCharacterOfPreviousLine(regionCtx.StartPos)+1; regionCtxStack.Push(regionCtx); } goto skipToEndOfLine; case "endregion": if (insideExcludedBlock) goto skipToEndOfLine; if (this.regionCount <= 0) this.HandleError(Error.UnexpectedDirective); else this.regionCount--; if (this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0){ SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop(); startRegionCtx.EndPos = this.endPos; this.sink.AddCollapsibleRegion(startRegionCtx, true); if (this.regionCtxStack.Count == 0) this.regionCtxStack = null; } goto skipToEndOfLine; case "pragma": this.SkipBlanks(); this.startPos = --this.endPos; this.ScanIdentifier(); string identString = this.GetIdentifierString(); if (identString != "warning") { this.HandleError(Error.UnexpectedDirective); goto skipToEndOfLine; } this.SkipBlanks(); this.startPos = --this.endPos; this.ScanIdentifier(); identString = this.GetIdentifierString(); bool disable; if (identString == "disable") { disable = true; } else if (identString == "restore") { disable = false; } else { this.HandleError(Error.ErrorDirective); goto skipToEndOfLine; } while (true) { this.SkipBlanks(); this.startPos = --this.endPos; c = this.GetChar(this.endPos); if (this.IsEndLineOrEOF(c, 0)) return exclude; if (c < '0' || c > '9') { this.HandleError(Error.IntegralTypeValueExpected); goto skipToEndOfLine; } while ('0' <= (c = this.GetChar(++this.endPos)) && c <= '9') ; int warnNum; try { warnNum = int.Parse(this.GetTokenSource(), CultureInfo.InvariantCulture); if (warnNum <= 0) { this.startPos = this.endPos; this.HandleError(Error.Warning); goto skipToEndOfLine; } } catch (OverflowException) { this.startPos++; this.HandleError(Error.IntOverflow); goto skipToEndOfLine; } PragmaInfo pragmaInfo = (PragmaInfo)this.pragmaInformation[warnNum]; this.pragmaInformation[warnNum] = new PragmaInfo(this.CurrentSourceContext.StartLine, disable, pragmaInfo); if (this.SkipBlanks() != ',') break; } goto skipToEndOfLine; default: if (insideExcludedBlock) goto skipToEndOfLine; this.HandleError(Error.PPDirectiveExpected); goto skipToEndOfLine; } char ch = this.SkipBlanks(); if (this.IsEndLineOrEOF(ch, 0)) return exclude; if (ch == '/' && (ch = this.GetChar(this.endPos++)) == '/') goto skipToEndOfLine; this.startPos = this.endPos-1; this.HandleError(Error.EndOfPPLineExpected); skipToEndOfLine: this.SkipSingleLineComment(); return exclude; }