private void ProcessDefineUse(PreprocessorParams p, string name) { var rdr = p.reader; if (p.suppress) { rdr.Use(name.Length); return; } if (p.restrictedDefines != null && p.restrictedDefines.Contains(name)) { rdr.Use(name.Length); return; } PreprocessorDefine define = null; if (p.args != null) { foreach (var arg in p.args) { if (arg.Name == name) { define = arg; break; } } } if (define == null) { _defines.TryGetValue(name, out define); } if (define == null || define.Disabled) { rdr.Use(name.Length); return; } var nameFilePos = rdr.FilePosition; if (nameFilePos.IsInFile) { _refs.Add(new Reference(define.Definition, nameFilePos)); } if (define.DataType != null && name == define.DataType.Name) { // Insert the data type name before the data type, so that it's available in the quick info and database. rdr.Insert(string.Format("@{0} ", DataType.NormalizeEnumOption(name))); } rdr.Ignore(name.Length); p.result.DocumentAltered = true; List <string> paramList = null; if (define.ParamNames != null) { // This is a parameterized macro rdr.IgnoreWhiteSpaceAndComments(false); if (rdr.Peek() != '(') { return; } rdr.Ignore(1); char ch; var sb = new StringBuilder(); paramList = new List <string>(); rdr.IgnoreWhiteSpaceAndComments(false); while (!rdr.EOF) { if (rdr.IgnoreComments()) { continue; } ch = rdr.Peek(); if (ch == ',') { rdr.Ignore(1); var argText = ApplySubstitutions(sb.ToString(), p.args); var resolvedParamText = ResolveMacros(argText, p.restrictedDefines, null, p.fileContext, p.contentType); paramList.Add(resolvedParamText.Trim()); sb.Clear(); } else if (ch == ')') { rdr.Ignore(1); break; } else if (ch == '(') { rdr.Ignore(1); sb.Append('('); sb.Append(rdr.ReadAndIgnoreNestableContent(")")); sb.Append(')'); } else if (ch == '{') { rdr.Ignore(1); sb.Append('{'); sb.Append(rdr.ReadAndIgnoreNestableContent("}")); sb.Append('}'); } else if (ch == '[') { rdr.Ignore(1); sb.Append('['); sb.Append(rdr.ReadAndIgnoreNestableContent("]")); sb.Append(']'); } else if (ch == '\'' || ch == '\"') { sb.Append(rdr.ReadAndIgnoreStringLiteral()); } else { rdr.Ignore(1); sb.Append(ch); } } if (sb.Length > 0) { var argText = ApplySubstitutions(sb.ToString(), p.args); var resolvedParamText = ResolveMacros(argText, p.restrictedDefines, null, p.fileContext, p.contentType); paramList.Add(resolvedParamText.Trim()); } if (define.ParamNames.Count != paramList.Count) { return; } } var oldArgs = p.args; List <PreprocessorDefine> args = null; if (paramList != null) { if (define.ParamNames == null || define.ParamNames.Count != paramList.Count) { return; } if (args == null) { args = new List <PreprocessorDefine>(); } for (int i = 0, ii = paramList.Count; i < ii; i++) { args.Add(new PreprocessorDefine(define.ParamNames[i], paramList[i], null, FilePosition.Empty)); } } if (p.args != null && p.args.Any()) { if (args == null) { args = new List <PreprocessorDefine>(); } args.AddRange(p.args); } string[] restrictedDefines = null; if (p.restrictedDefines != null) { restrictedDefines = p.restrictedDefines.Concat(new string[] { name }).ToArray(); } else { restrictedDefines = new string[] { name } }; var textToAdd = ApplySubstitutions(define.Content, args); textToAdd = ResolveMacros(textToAdd, restrictedDefines, null, p.fileContext, p.contentType); rdr.Insert(textToAdd); p.args = oldArgs; }
private PreprocessorResult Preprocess(PreprocessorParams p) { // This function assumes the source has already been merged. if (_defines == null) { _defines = new Dictionary <string, PreprocessorDefine>(); _defines["_WINDOWS"] = new PreprocessorDefine("_WINDOWS", string.Empty, null, FilePosition.Empty); } if (p.stdlibDefines != null) { foreach (var def in p.stdlibDefines) { _defines[def.Name] = def; } } string str; var sb = new StringBuilder(); var rdr = p.reader; p.reader.SetWriter(p.writer); while (!rdr.EOF && !p.result.IncludeFileReached) { str = rdr.PeekToken(false); if (string.IsNullOrEmpty(str)) { continue; } if (str[0] == '#') { ProcessDirective(p, str); continue; } if (p.suppress) { rdr.Ignore(str.Length); continue; } if (str[0].IsWordChar(true)) { if (p.args != null && p.args.Any(x => x.Name == str)) { ProcessDefineUse(p, str); } else if (_defines.ContainsKey(str)) { ProcessDefineUse(p, str); } else if (str == "STRINGIZE") { rdr.Ignore(str.Length); p.result.DocumentAltered = true; ProcessStringizeKeyword(p); } else if (str == "defined" && p.contentType == ContentType.Condition) { rdr.Ignore(str.Length); p.result.DocumentAltered = true; ProcessDefinedKeyword(p); } else { rdr.Use(str.Length); } continue; } if (str == "@") { // This is the start of the name portion of a data type definition. rdr.Use(str.Length); var name = rdr.PeekToken(true); if (name.IsWord()) { rdr.Use(name.Length); } continue; } rdr.Use(str.Length); } p.writer.Flush(); return(p.result); }
private void ProcessDefine(PreprocessorParams p) { var rdr = p.reader; char ch; string str; // Get the define name rdr.IgnoreWhiteSpaceAndComments(true); var linkFilePos = rdr.FilePosition; var name = rdr.PeekIdentifier(); if (string.IsNullOrEmpty(name)) { return; } var nameFilePos = rdr.FilePosition; rdr.Ignore(name.Length); // Check if this is parameterized List <string> paramNames = null; if (rdr.Peek() == '(') { rdr.Ignore(1); while (!rdr.EOF) { rdr.IgnoreWhiteSpaceAndComments(true); str = rdr.PeekToken(false); if (string.IsNullOrEmpty(str)) { return; } if (str == ",") { rdr.Ignore(str.Length); } else if (str[0].IsWordChar(true)) { rdr.Ignore(str.Length); if (!p.suppress) { if (paramNames == null) { paramNames = new List <string>(); } paramNames.Add(str); } } else if (str == ")") { rdr.Ignore(str.Length); break; } else { return; } } } // Read the define value rdr.IgnoreWhiteSpaceAndComments(true); var insideBlock = false; var braceLevel = 0; ch = rdr.Peek(); if (ch == '{') { insideBlock = true; braceLevel = 1; rdr.Ignore(1); } var sb = new StringBuilder(); while (!rdr.EOF) { if (rdr.IgnoreComments()) { continue; } str = rdr.PeekToken(true); if (str == null) { // End of line found char endCh; int index; if (sb.GetLastNonWhiteChar(out endCh, out index)) { if (endCh == '\\') { // define continues down to the next line, but don't include the slash in the resulting text. sb.Remove(index, 1); if (insideBlock) { sb.Append("\r\n"); } //rdr.IgnoreUntil(c => c == '\r' || c == '\n'); rdr.IgnoreWhile(PreprocessorReaderExtensions.LineEndChars); continue; } else if (insideBlock) { //rdr.IgnoreUntil(c => c == '\r' || c == '\n'); rdr.IgnoreWhile(PreprocessorReaderExtensions.LineEndChars); sb.Append("\r\n"); continue; } else { break; } } else { if (insideBlock) { //rdr.IgnoreUntil(c => c == '\r' || c == '\n'); rdr.IgnoreWhile(PreprocessorReaderExtensions.LineEndChars); sb.Append("\r\n"); continue; } else { break; } } } if (str == "{" && insideBlock) { braceLevel++; rdr.Ignore(str.Length); sb.Append('{'); continue; } if (str == "}" && insideBlock) { rdr.Ignore(str.Length); if (--braceLevel <= 0) { break; } else { sb.Append('}'); continue; } } rdr.Ignore(str.Length); sb.Append(str); } if (!p.suppress) { var define = new PreprocessorDefine(name, sb.ToString().Trim(), paramNames, linkFilePos); _defines[name] = define; if (nameFilePos.IsInFile) { _refs.Add(new Reference(define.Definition, nameFilePos)); } } }