private string InjectParams(MacroDef macro, List <string> values) { var ps = macro.Parameters.Zip(values, Tuple.Create).ToList();; var parts = macro.BodyParts; for (int i = 0; i < parts.Length; i++) { foreach (var p in ps) { parts[i] = parts[i].Replace("#" + p.Item1, "\"" + p.Item2 + "\""); parts[i] = parts[i].Replace(p.Item1, p.Item2); } } return(string.Join("", parts)); }
private string ExpandMacro(Match m, MacroDef macro) { if (macro.Parameters.Length == 0) { return(PreprocessLine(macro.Body)); } else { var s = m.Groups[1].Value; var pos = 0; var level = 0; var ps = new List <string>(macro.Parameters.Length); var currentParam = new StringBuilder(); while (pos < s.Length) { if ("([{".Contains(s[pos])) { level++; } if (")]}".Contains(s[pos])) { level--; } if (s[pos] == ',' && level == 0) { //next param ps.Add(currentParam.ToString()); currentParam.Clear(); } else { currentParam.Append(s[pos]); } pos++; } ps.Add(currentParam.ToString()); var pps = ps.Select(PreprocessLine).ToList(); return(PreprocessLine(InjectParams(macro, pps))); } }
private IEnumerable <FileLine> Prepocess() { string s; newLine: while ((s = reader.ReadLine()) != null) { var ss = s; lineNumber++; if (!insideComment) { var idx = s.IndexOf("/*"); if (idx > -1) { ss = s.Substring(0, idx); insideComment = true; } } else { var idx = s.IndexOf("*/"); if (idx > -1) { ss = s.Substring(idx + 2); insideComment = false; } else { continue; } } var commentIdx = ss.IndexOf("//"); if (commentIdx > -1) { ss = ss.Substring(0, commentIdx); } if (ss.Trim().StartsWith("#")) { ss = ss.TrimStart(); //Parse preprocessor if (ss.Trim() == "#endif") { supress = false; wasIf = false; } if (ss.Trim() == "#else") { if (wasIf) { supress = !supress; } else { throw new FormatException(string.Format("Unmatched #else in {0} line {1}", fileName, lineNumber)); } } if (supress) { goto newLine; } if (ss.StartsWith("#ifdef")) { var m = s.Substring("#ifdef".Length + 1); supress = !macros.ContainsKey(m); wasIf = true; } if (ss.StartsWith("#ifndef")) { var m = s.Substring("#ifndef".Length + 1); supress = macros.ContainsKey(m); wasIf = true; } if (ss.StartsWith("#undef")) { var m = s.Substring("#undef".Length + 1); macros.Remove(m); } if (ss.StartsWith("#define")) { var macro = new MacroDef { Line = lineNumber, File = fileName }; var block = ss.Substring("#define".Length + 1); while (block.EndsWith("\\")) { ss = reader.ReadLine(); block = block.TrimEnd('\\') + ss; lineNumber++; } var m = defineParser.Match(block); if (!m.Success) { throw new FormatException(string.Format("Error parsing define at {0} line {1}", fileName, lineNumber)); } macro.Name = m.Groups["name"].Value; macro.Body = m.Groups["body"].Value; macro.Parameters = m.Groups["params"].Value.Split(',').Select(p => p.Trim()).Where(p => !string.IsNullOrEmpty(p)).ToArray(); macro.Prepare(); macros[macro.Name] = macro; } if (ss.StartsWith("#include")) { var f = ss.Substring("#include".Length + 1).Trim('"', ' ', '<', '>'); var l = lookupFile(fileName, f); var p = new Preprocessor(l.Item1, l.Item2, lookupFile, macros); foreach (var x in p.Prepocess()) { yield return(x); } } continue; } if (supress) { goto newLine; } if (s.Length > 0) { yield return(new FileLine(fileName, lineNumber, PreprocessLine(s))); } } }