Beispiel #1
0
        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);
        }
Beispiel #2
0
        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();
        }