CompacterDirectives ParseDirectives(Stack <String> debugFileStack, String code, CompacterDirectives parentDirectives) { CompacterDirectives directives = parentDirectives.Clone(); foreach (Match match in CompacterDirectiveRegex.Matches(code)) { String directive = match.Groups[1].Value; switch (directive) { case "cpp-only": directives.CppOnly = true; break; default: this.EmitWarning(debugFileStack, "Unknown 'compacter' directive '" + match.Groups[1].Value + "'"); break; } } return(directives); }
void ProcessCodeFile(Stack <String> debugFileStack, String codeFile, String code, CodeFileType type) { if (debugFileStack.Contains(codeFile)) { var builder = new StringBuilder(); foreach (var file in debugFileStack) { builder.AppendLine(" " + file); } throw new Exception("Cycle of inclusion detected: \n" + builder.ToString()); } debugFileStack.Push(codeFile); if (debugFileStack.Count == 50) { throw new Exception("Possible cycle of inclusion! Recursion depth was too deep"); } var directoryDirective = new CompacterDirectives(); var directoryPath = NormalizePath(Path.GetDirectoryName(codeFile)); if (this.DirectoryDirectives.ContainsKey(directoryPath)) { directoryDirective = this.DirectoryDirectives[directoryPath]; } var directives = this.ParseDirectives(debugFileStack, code, directoryDirective); if (this.OutputDirectory != null) { var pathToOutput = Path.Combine(this.OutputDirectory, Path.GetFileName(codeFile)); //if (File.Exists(pathToOutput) == false) //{ // File.WriteAllText(pathToOutput, code); //} //else if (File.ReadAllText(pathToOutput) != code) //{ // String error = "The file '" + Path.GetFileName(pathToOutput) + "' has the same name as another file"; // error = error; // //throw new Exception("The file '" + Path.GetFileName(pathToOutput) + "' has the same name as another file"); //} } // If this is meant to only be included in a cpp file, then just set the type to cpp if (directives.CppOnly) { type = CodeFileType.CppFile; // Remove all pragma once declarations code = PragmaOnceRegex.Replace(code, String.Empty); } if (directives.PreprocessorCondition != null) { this.AppendCodeSeparateLine(type, "#if " + directives.PreprocessorCondition); } int line = 1; // When we compile, we want to make sure we get errors in the correct places this.AttemptEmitLineDirective(type, line, codeFile); var fullName = codeFile; var strIndex = 0; // Scan for includes var matches = IncludeRegex.Matches(code); foreach (Match match in matches) { // Skip any includes that are commented out // This does NOT catch multi-line comments! if (SingleLineComment.IsMatch(match.Value)) { continue; } // Cpps include both cpp and header files int prevCodeLength = match.Index - strIndex; this.AppendCode(type, code, strIndex, prevCodeLength); line += this.CountLines(code, strIndex, prevCodeLength); strIndex = match.Index + match.Length; var includeFile = match.Groups[1].Value; var fullPathToIncludeFile = this.ScanForInclude(includeFile, Path.GetDirectoryName(codeFile), debugFileStack); if (fullPathToIncludeFile != null) { if (this.ProcessedOnceIncludeFiles.Contains(fullPathToIncludeFile) == false) { var includeStatus = this.ProcessIncludeCodeFile(debugFileStack, fullPathToIncludeFile, type); // We only ever add the include to the 'all includes' if it contains a pragma-once // Otherwise, we may want to reprocess that include if (includeStatus == IncludeStatus.PragmaOnce) { this.ProcessedOnceIncludeFiles.Add(fullPathToIncludeFile); } // Since we just entered another file (and probably emitted) and now we're back in our own file, emit a line directive again) this.AttemptEmitLineDirective(type, line, codeFile); } } else { var afterInclude = match.Groups[2].Value; if (afterInclude.Contains("@ignore") == false) { this.EmitWarning(debugFileStack, "Unable to find '" + includeFile + "'"); } this.AppendCode(type, match.Value, 0, match.Value.Length); } } this.AppendCode(type, code, strIndex, code.Length - strIndex); if (directives.PreprocessorCondition != null) { this.AppendCode(type, Environment.NewLine + "#endif" + Environment.NewLine); } debugFileStack.Pop(); }