Example #1
0
        public Preprocessor(Configuration options)
        {
            // primary source file is the one that wave is run against
            // to produce a single preprocessed monolithic header
            primarySource = Environment.ExpandEnvironmentVariables(options.PrimaryHeader);
            wavePath = "wave.exe";

            // -E indicates default naming scheme for output file (e.g. input.i)
            // -m macros.txt creates a separate file containing a list of all found macros
            // --variadics enables macros with empty argument lists (necessary for some win32 header)
            // -S adds an include path (specified in our config file)
            // -D adds a predefined macro (several are necessary to compile the win32 headers)
            // -r forcibly ignores a given definition
            // final argument is the primary header file to run against
            var builder = new StringBuilder("-E -m macros.txt --variadics ");

            foreach (var path in options.IncludePaths)
                builder.Append("-S \"").Append(Environment.ExpandEnvironmentVariables(path)).Append("\" ");

            foreach (var symbol in options.DefineSymbols)
                builder.Append("-D ").Append(symbol).Append(" ");

            foreach (var symbol in options.IgnoreSymbols)
                builder.Append("-r ").Append(symbol).Append(" ");

            Source = Path.GetFileName(primarySource);
            builder.AppendFormat("\"{0}\"", Source);
            arguments = builder.ToString();
        }
Example #2
0
        static void RunGenerator(ApiModel api, Configuration configuration)
        {
            var templateDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Templates");
            var templateEngine = new TemplateEngine(new[] { templateDirectory });

            templateEngine.RegisterCallback("ApiNamespace", (e, s) => api.Name);
            templateEngine.RegisterCallback("ApiName", (e, s) => TemplateCallbacks.GetApiClassName(api));
            templateEngine.RegisterCallback("ApiDll", (e, s) => TemplateCallbacks.GetApiDllName(api));
            templateEngine.RegisterCallbacks(typeof(TemplateCallbacks));

            var outputDirectory = configuration.GeneratorOutputPath;
            if (!Directory.Exists(outputDirectory))
                Directory.CreateDirectory(outputDirectory);

            ApplyTemplate(api, outputDirectory, templateEngine, "Api");
            ApplyTemplate(api.Enumerations, outputDirectory, templateEngine, "Enumeration");
            ApplyTemplate(api.Structures, outputDirectory, templateEngine, "Structure");
            ApplyTemplate(api.Interfaces, outputDirectory, templateEngine, "Interface");

            BuildTrampolineAssembly(api, outputDirectory, string.Format("{0}.Trampoline", api.Name));
        }
Example #3
0
        static JObject RunParser(Configuration configuration)
        {
            // run boost::wave on the primary source file to get a preprocessed file and a list of macros
            var preprocessor = new Preprocessor(configuration);
            Console.WriteLine(preprocessor.Run());

            // before parsing, run some transformations on the preprocessed file to cut down on the size needed to be examined
            // this includes dropping any source that is not from the given primary or ancillary
            // sources, which is indicated in the preprocessed file by #line directives
            var source = preprocessor.Source;
            var rawSources = configuration.AdditionalHeaders.Concat(new[] { Path.Combine(Directory.GetCurrentDirectory(), source) });
            var relevantSources = new List<string>();
            foreach (string s in rawSources)
                relevantSources.Add(Environment.ExpandEnvironmentVariables(s));

            source = Path.ChangeExtension(source, ".i");
            Preprocessor.PostTransform(source, new HashSet<string>(relevantSources));

            // run the parser on the preprocessed file to generate a model of the file in memory
            var grammarFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "header_grammar.cgt");
            var parser = new HeaderParser(grammarFile);
            var root = parser.Parse(source).ToXml();
            var json = ModelXml.Transform(root);

            // add a dependency to the base SlimDX.json file
            json.Add(new JProperty("dependencies", new JArray(new JValue("../SlimDX/SlimDX.json"))));

            return json;
        }
Example #4
0
        /// <summary>
        /// The application's entry point.
        /// </summary>
        /// <param name="arguments">The command line arguments.</param>
        static void Main(string[] arguments)
        {
            if (arguments.Length == 0)
                throw new InvalidOperationException("Missing configuration file path.");

            var configuration = new Configuration(arguments[0]);

            var searchPaths = new HashSet<string>();
            var json = RunParser(configuration);
            foreach (var layer in configuration.Layers)
            {
                JObject current = null;
                current = JObject.Parse(File.ReadAllText(layer));
                searchPaths.Add(Path.GetDirectoryName(Path.GetFullPath(layer)));

                // combine the current layer with the base
                if (json == null)
                    json = current;
                else
                    CompositingEngine.Compose(json, current);
            }

            var generatedModelFile = Path.Combine(configuration.GeneratorOutputPath, configuration.ApiName + ".json");
            File.WriteAllText(generatedModelFile, json.ToString());

            // run the generator on the composed Json model
            var api = ModelJson.Parse(json, searchPaths);
            RunGenerator(api, configuration);
        }