mirror of https://github.com/mono/CppSharp.git
14 changed files with 3219 additions and 0 deletions
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
using System; |
||||
using System.Linq; |
||||
using System.Xml.Linq; |
||||
using System.Collections.Generic; |
||||
|
||||
public enum FilterMode { |
||||
Include, |
||||
Exclude, |
||||
External |
||||
} |
||||
|
||||
public enum ImplementationType { |
||||
@class, |
||||
@struct |
||||
} |
||||
|
||||
public struct Filter { |
||||
|
||||
public string TypeName { get; set; } |
||||
public FilterMode Mode { get; set; } |
||||
public ImplementationType ImplType { get; set; } |
||||
|
||||
public static Dictionary<string, Filter> Load (XDocument doc, out FilterMode @default) |
||||
{ |
||||
string value; |
||||
@default = (value = (string)doc.Root.Attribute ("default")) != null ? (FilterMode)Enum.Parse (typeof (FilterMode), value) : FilterMode.Include; |
||||
|
||||
var rules = from rule in doc.Root.Elements () |
||||
let mode = (FilterMode)Enum.Parse (typeof (FilterMode), rule.Name.LocalName) |
||||
let impl = (value = (string)rule.Attribute ("implementation")) != null ? (ImplementationType)Enum.Parse (typeof (ImplementationType), value) : ImplementationType.@class |
||||
select new Filter { TypeName = rule.Value, Mode = mode, ImplType = impl }; |
||||
|
||||
|
||||
return rules.ToDictionary<Filter,string> (r => r.TypeName); |
||||
} |
||||
} |
@ -0,0 +1,243 @@
@@ -0,0 +1,243 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
using Cxxi; |
||||
using Cxxi.Templates; |
||||
|
||||
public partial class Generator |
||||
{ |
||||
public List<Transformation> Transformations { get; set; } |
||||
|
||||
Library Library; |
||||
Options Options; |
||||
|
||||
public Generator(Library library, Options options) |
||||
{ |
||||
Transformations = new List<Transformation>(); |
||||
|
||||
Library = library; |
||||
Options = options; |
||||
} |
||||
|
||||
public void Process() |
||||
{ |
||||
TransformModule(); |
||||
ProcessModules(); |
||||
} |
||||
|
||||
// Generates the binding code.
|
||||
public void Generate() |
||||
{ |
||||
GenerateModules(); |
||||
} |
||||
|
||||
int UniqueType = 0; |
||||
|
||||
void CleanupText(ref string debugText) |
||||
{ |
||||
// Strip off newlines from the debug text.
|
||||
if (String.IsNullOrWhiteSpace(debugText)) |
||||
debugText = String.Empty; |
||||
|
||||
// TODO: Make this transformation in the output.
|
||||
debugText = Regex.Replace(debugText, " ( )+", " "); |
||||
debugText = Regex.Replace(debugText, "\n", ""); |
||||
} |
||||
|
||||
void ProcessType(Declaration type) |
||||
{ |
||||
// If after all the transformations the type still does
|
||||
// not have a name, then generate one.
|
||||
|
||||
if (String.IsNullOrWhiteSpace(type.Name)) |
||||
type.Name = String.Format("UnnamedType{0}", UniqueType++); |
||||
|
||||
CleanupText(ref type.DebugText); |
||||
} |
||||
|
||||
void ProcessTypes<T>(List<T> types) where T : Declaration |
||||
{ |
||||
foreach (T type in types) |
||||
ProcessType(type); |
||||
} |
||||
|
||||
void ProcessClasses(List<Class> Classes) |
||||
{ |
||||
ProcessTypes(Classes); |
||||
|
||||
foreach (var @class in Classes) |
||||
ProcessTypes(@class.Fields); |
||||
} |
||||
|
||||
void ProcessFunctions(List<Function> Functions) |
||||
{ |
||||
ProcessTypes(Functions); |
||||
|
||||
foreach (var function in Functions) |
||||
{ |
||||
if (function.ReturnType == null) |
||||
{ |
||||
// Ignore and warn about unknown types.
|
||||
function.Ignore = true; |
||||
|
||||
var s = "Function '{0}' was ignored due to unknown return type..."; |
||||
Console.WriteLine( String.Format(s, function.Name) ); |
||||
} |
||||
|
||||
ProcessTypes(function.Parameters); |
||||
} |
||||
} |
||||
|
||||
void ProcessModules() |
||||
{ |
||||
if (String.IsNullOrEmpty(Library.Name)) |
||||
Library.Name = ""; |
||||
|
||||
// Process everything in the global namespace for now.
|
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
ProcessNamespace(module.Global); |
||||
} |
||||
} |
||||
|
||||
void ProcessNamespace(Namespace @namespace) |
||||
{ |
||||
ProcessTypes(@namespace.Enums); |
||||
ProcessFunctions(@namespace.Functions); |
||||
ProcessClasses(@namespace.Classes); |
||||
} |
||||
|
||||
void TransformModule() |
||||
{ |
||||
if (String.IsNullOrEmpty(Library.Name)) |
||||
Library.Name = ""; |
||||
|
||||
// Process everything in the global namespace for now.
|
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
Namespace global = module.Global; |
||||
|
||||
foreach (Enumeration @enum in global.Enums) |
||||
TransformEnum(@enum); |
||||
|
||||
foreach (Function function in global.Functions) |
||||
TransformFunction(function); |
||||
|
||||
foreach (Class @class in global.Classes) |
||||
TransformClass(@class); |
||||
} |
||||
} |
||||
|
||||
void TransformType(Declaration type) |
||||
{ |
||||
foreach (var transform in Transformations) |
||||
transform.ProcessType(type); |
||||
} |
||||
|
||||
void TransformClass(Class @class) |
||||
{ |
||||
TransformType(@class); |
||||
|
||||
foreach (var field in @class.Fields) |
||||
TransformType(field); |
||||
} |
||||
|
||||
void TransformFunction(Function function) |
||||
{ |
||||
TransformType(function); |
||||
|
||||
foreach (var param in function.Parameters) |
||||
TransformType(param); |
||||
} |
||||
|
||||
|
||||
void TransformEnum(Enumeration @enum) |
||||
{ |
||||
TransformType(@enum); |
||||
|
||||
foreach (var transform in Transformations) |
||||
{ |
||||
foreach (var item in @enum.Items) |
||||
transform.ProcessEnumItem(item); |
||||
} |
||||
|
||||
// If the enumeration only has power of two values, assume it's
|
||||
// a flags enum.
|
||||
|
||||
bool isFlags = true; |
||||
bool hasBigRange = false; |
||||
|
||||
foreach (var item in @enum.Items) |
||||
{ |
||||
if (item.Name.Length >= 1 && Char.IsDigit(item.Name[0])) |
||||
item.Name = String.Format("_{0}", item.Name); |
||||
|
||||
long value = item.Value; |
||||
if (value >= 4) |
||||
hasBigRange = true; |
||||
if (value <= 1 || value.IsPowerOfTwo()) |
||||
continue; |
||||
isFlags = false; |
||||
} |
||||
|
||||
// Only apply this heuristic if there are enough values to have a
|
||||
// reasonable chance that it really is a bitfield.
|
||||
|
||||
if (isFlags && hasBigRange) |
||||
{ |
||||
@enum.Modifiers |= Enumeration.EnumModifiers.Flags; |
||||
} |
||||
|
||||
// If we still do not have a valid name, then try to guess one
|
||||
// based on the enum value names.
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(@enum.Name)) |
||||
return; |
||||
|
||||
var names = new List<string>(); |
||||
|
||||
foreach (var item in @enum.Items) |
||||
names.Add(item.Name); |
||||
|
||||
var prefix = names.ToArray().CommonPrefix(); |
||||
|
||||
// Try a simple heuristic to make sure we end up with a valid name.
|
||||
if (prefix.Length >= 3) |
||||
{ |
||||
prefix = prefix.Trim().Trim(new char[] { '_' }); |
||||
@enum.Name = prefix; |
||||
} |
||||
} |
||||
|
||||
void GenerateModules() |
||||
{ |
||||
// Process everything in the global namespace for now.
|
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
if (module.Ignore || !module.HasDeclarations) |
||||
continue; |
||||
|
||||
// Generate the code from templates.
|
||||
var template = new CSharpModule(); |
||||
template.Library = Library; |
||||
template.Options = Options; |
||||
template.Module = module; |
||||
|
||||
if (!Directory.Exists(Options.OutputDir)) |
||||
Directory.CreateDirectory(Options.OutputDir); |
||||
|
||||
var file = Path.GetFileNameWithoutExtension(module.FileName) + ".cs"; |
||||
var path = Path.Combine(Options.OutputDir, file); |
||||
|
||||
// Normalize path.
|
||||
path = Path.GetFullPath(path); |
||||
|
||||
string code = template.TransformText(); |
||||
|
||||
Console.WriteLine(" Generated '" + file + "'."); |
||||
File.WriteAllText(path, code); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<PropertyGroup> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> |
||||
<ProductVersion>8.0.30703</ProductVersion> |
||||
<SchemaVersion>2.0</SchemaVersion> |
||||
<ProjectGuid>{73499B8E-A6A4-42FF-AB8A-754CE2780777}</ProjectGuid> |
||||
<OutputType>Exe</OutputType> |
||||
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
<RootNamespace>Cxxi</RootNamespace> |
||||
<AssemblyName>Generator</AssemblyName> |
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile> |
||||
<FileAlignment>512</FileAlignment> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> |
||||
<PlatformTarget>x86</PlatformTarget> |
||||
<DebugSymbols>true</DebugSymbols> |
||||
<DebugType>full</DebugType> |
||||
<Optimize>false</Optimize> |
||||
<OutputPath>$(SolutionDir)bin\</OutputPath> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
<UseVSHostingProcess>true</UseVSHostingProcess> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> |
||||
<PlatformTarget>x86</PlatformTarget> |
||||
<DebugType>pdbonly</DebugType> |
||||
<Optimize>true</Optimize> |
||||
<OutputPath>bin\Release\</OutputPath> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<PropertyGroup> |
||||
<StartupObject>Program</StartupObject> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<Reference Include="Parser_d"> |
||||
<HintPath>..\..\bin\Parser_d.dll</HintPath> |
||||
</Reference> |
||||
<Reference Include="System" /> |
||||
<Reference Include="System.Core" /> |
||||
<Reference Include="System.Xml.Linq" /> |
||||
<Reference Include="System.Data.DataSetExtensions" /> |
||||
<Reference Include="Microsoft.CSharp" /> |
||||
<Reference Include="System.Data" /> |
||||
<Reference Include="System.Xml" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Compile Include="Filter.cs" /> |
||||
<Compile Include="Generator.cs" /> |
||||
<Compile Include="Glob.cs" /> |
||||
<Compile Include="Helpers.cs" /> |
||||
<Compile Include="Options.cs" /> |
||||
<Compile Include="Program.cs" /> |
||||
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||
<Compile Include="Templates\CSharpModule.cs"> |
||||
<AutoGen>True</AutoGen> |
||||
<DesignTime>True</DesignTime> |
||||
<DependentUpon>CSharpModule.tt</DependentUpon> |
||||
</Compile> |
||||
<Compile Include="Transform.cs" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<None Include="packages.config" /> |
||||
<None Include="Templates\CSharpModule.tt"> |
||||
<Generator>TextTemplatingFilePreprocessor</Generator> |
||||
<LastGenOutput>CSharpModule.cs</LastGenOutput> |
||||
</None> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="..\Bridge\Bridge.csproj"> |
||||
<Project>{6BEB8FA2-97AA-40B7-AB92-42F6EDDC4490}</Project> |
||||
<Name>Bridge</Name> |
||||
</ProjectReference> |
||||
</ItemGroup> |
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
||||
Other similar extension points exist, see Microsoft.Common.targets. |
||||
<Target Name="BeforeBuild"> |
||||
</Target> |
||||
<Target Name="AfterBuild"> |
||||
</Target> |
||||
--> |
||||
</Project> |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> |
||||
<EnableUnmanagedDebugging>true</EnableUnmanagedDebugging> |
||||
<StartArguments>--debug --ns=SDL -outdir=gen/build/NSDL SDL/SDL.h</StartArguments> |
||||
<StartWorkingDirectory>C:\Development\cxxi\bin\</StartWorkingDirectory> |
||||
</PropertyGroup> |
||||
</Project> |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<TransformationPropertyValues xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
||||
<Values> |
||||
<TransformationPropertyValue> |
||||
<FileName>Templates\CSharpModule.tt</FileName> |
||||
<PropertyName>Host</PropertyName> |
||||
<Value>VisualStudio</Value> |
||||
</TransformationPropertyValue> |
||||
</Values> |
||||
</TransformationPropertyValues> |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
|
||||
public static class Glob |
||||
{ |
||||
static public string[] GetFiles(string[] patterns) |
||||
{ |
||||
List<string> filelist = new List<string>(); |
||||
foreach (string pattern in patterns) |
||||
filelist.AddRange(GetFiles(pattern)); |
||||
string[] files = new string[filelist.Count]; |
||||
filelist.CopyTo(files, 0); |
||||
return files; |
||||
} |
||||
|
||||
static public string[] GetFiles(string patternlist) |
||||
{ |
||||
List<string> filelist = new List<string>(); |
||||
foreach (string pattern in |
||||
patternlist.Split(Path.GetInvalidPathChars())) |
||||
{ |
||||
string dir = Path.GetDirectoryName(pattern); |
||||
if (String.IsNullOrEmpty(dir)) dir = |
||||
Directory.GetCurrentDirectory(); |
||||
filelist.AddRange(Directory.GetFiles( |
||||
Path.GetFullPath(dir), |
||||
Path.GetFileName(pattern))); |
||||
} |
||||
string[] files = new string[filelist.Count]; |
||||
filelist.CopyTo(files, 0); |
||||
return files; |
||||
} |
||||
} |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
namespace Cxxi.Templates |
||||
{ |
||||
public partial class CSharpModule |
||||
{ |
||||
public Library Library; |
||||
public Options Options; |
||||
public Module Module; |
||||
|
||||
readonly string DefaultIndent = " "; |
||||
|
||||
// from https://github.com/mono/mono/blob/master/mcs/class/System/Microsoft.CSharp/CSharpCodeGenerator.cs
|
||||
private static string[] keywords = new string[] |
||||
{ |
||||
"abstract","event","new","struct","as","explicit","null","switch","base","extern", |
||||
"this","false","operator","throw","break","finally","out","true", |
||||
"fixed","override","try","case","params","typeof","catch","for", |
||||
"private","foreach","protected","checked","goto","public", |
||||
"unchecked","class","if","readonly","unsafe","const","implicit","ref", |
||||
"continue","in","return","using","virtual","default", |
||||
"interface","sealed","volatile","delegate","internal","do","is", |
||||
"sizeof","while","lock","stackalloc","else","static","enum", |
||||
"namespace", |
||||
"object","bool","byte","float","uint","char","ulong","ushort", |
||||
"decimal","int","sbyte","short","double","long","string","void", |
||||
"partial", "yield", "where" |
||||
}; |
||||
|
||||
public static string SafeIdentifier(string proposedName) |
||||
{ |
||||
proposedName = new string(((IEnumerable<char>)proposedName).Select(c => char.IsLetterOrDigit(c) ? c : '_').ToArray()); |
||||
return keywords.Contains(proposedName) ? "@" + proposedName : proposedName; |
||||
} |
||||
} |
||||
|
||||
public static class IntHelpers |
||||
{ |
||||
public static bool IsPowerOfTwo(this long x) |
||||
{ |
||||
return (x != 0) && ((x & (x - 1)) == 0); |
||||
} |
||||
} |
||||
|
||||
public static class StringHelpers |
||||
{ |
||||
public static string CommonPrefix(this string[] ss) |
||||
{ |
||||
if (ss.Length == 0) |
||||
{ |
||||
return ""; |
||||
} |
||||
|
||||
if (ss.Length == 1) |
||||
{ |
||||
return ss[0]; |
||||
} |
||||
|
||||
int prefixLength = 0; |
||||
|
||||
foreach (char c in ss[0]) |
||||
{ |
||||
foreach (string s in ss) |
||||
{ |
||||
if (s.Length <= prefixLength || s[prefixLength] != c) |
||||
{ |
||||
return ss[0].Substring(0, prefixLength); |
||||
} |
||||
} |
||||
prefixLength++; |
||||
} |
||||
|
||||
return ss[0]; // all strings identical
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,181 @@
@@ -0,0 +1,181 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using Mono.Options; |
||||
using Cxxi; |
||||
|
||||
public class Options |
||||
{ |
||||
public bool Verbose = false; |
||||
public string IncludeDirs; |
||||
public string OutputDir; |
||||
public bool ShowHelpText = false; |
||||
public bool OutputDebug = false; |
||||
public string OutputNamespace; |
||||
public List<string> Headers; |
||||
} |
||||
|
||||
class Program |
||||
{ |
||||
static void ShowHelp(OptionSet options) |
||||
{ |
||||
var module = Process.GetCurrentProcess().MainModule; |
||||
var exeName = Path.GetFileName(module.FileName); |
||||
Console.WriteLine("Usage: " + exeName + " [options]+ headers"); |
||||
Console.WriteLine("Generates C# bindings from C/C++ header files."); |
||||
Console.WriteLine(); |
||||
Console.WriteLine("Options:"); |
||||
options.WriteOptionDescriptions(Console.Out); |
||||
} |
||||
|
||||
bool ParseCommandLineOptions(String[] args) |
||||
{ |
||||
var set = new OptionSet() |
||||
{ |
||||
// Parser options
|
||||
{ "C|compiler=", v => new object() }, |
||||
{ "D|defines=", v => new object() }, |
||||
{ "I|include=", v => options.IncludeDirs = v }, |
||||
// Generator options
|
||||
{ "ns|namespace=", v => options.OutputNamespace = v }, |
||||
{ "o|outdir=", v => options.OutputDir = v }, |
||||
{ "debug", v => options.OutputDebug = true }, |
||||
// Misc. options
|
||||
{ "v|verbose", v => { options.Verbose = true; } }, |
||||
{ "h|?|help", v => options.ShowHelpText = v != null }, |
||||
}; |
||||
|
||||
if (args.Length == 0 || options.ShowHelpText) |
||||
{ |
||||
ShowHelp(set); |
||||
return false; |
||||
} |
||||
|
||||
try |
||||
{ |
||||
options.Headers = set.Parse(args); |
||||
} |
||||
catch (OptionException ex) |
||||
{ |
||||
Console.WriteLine("Error parsing the command line."); |
||||
ShowHelp(set); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
Library library; |
||||
Options options; |
||||
|
||||
public void GenerateCode() |
||||
{ |
||||
Console.WriteLine("Generating wrapper code..."); |
||||
|
||||
if (library.Modules.Count > 0) |
||||
{ |
||||
var gen = new Generator(library, options); |
||||
TransformSDL(gen); |
||||
gen.Generate(); |
||||
} |
||||
} |
||||
|
||||
public void ParseNativeHeaders() |
||||
{ |
||||
Console.WriteLine("Parsing native code..."); |
||||
|
||||
foreach (var file in options.Headers) |
||||
{ |
||||
var path = String.Empty; |
||||
|
||||
try |
||||
{ |
||||
path = Path.GetFullPath(file); |
||||
} |
||||
catch (ArgumentException ex) |
||||
{ |
||||
Console.WriteLine("Invalid path '" + file + "'."); |
||||
continue; |
||||
} |
||||
|
||||
var Opts = new ParserOptions(); |
||||
Opts.FileName = path; |
||||
Opts.Library = library; |
||||
Opts.Verbose = false; |
||||
|
||||
if (!ClangParser.Parse(Opts)) |
||||
{ |
||||
Console.WriteLine(" Could not parse '" + file + "'."); |
||||
continue; |
||||
} |
||||
|
||||
Console.WriteLine(" Parsed '" + file + "'."); |
||||
} |
||||
} |
||||
|
||||
void TransformSDL(Generator g) |
||||
{ |
||||
g.IgnoreEnumWithMatchingItem("SDL_FALSE"); |
||||
g.IgnoreEnumWithMatchingItem("DUMMY_ENUM_VALUE"); |
||||
g.IgnoreEnumWithMatchingItem("SDL_ENOMEM"); |
||||
|
||||
g.SetNameOfEnumWithMatchingItem("SDL_SCANCODE_UNKNOWN", "ScanCode"); |
||||
g.SetNameOfEnumWithMatchingItem("SDLK_UNKNOWN", "Key"); |
||||
g.SetNameOfEnumWithMatchingItem("KMOD_NONE", "KeyModifier"); |
||||
g.SetNameOfEnumWithMatchingItem("SDL_LOG_CATEGORY_CUSTOM", "LogCategory"); |
||||
|
||||
g.GenerateEnumFromMacros("InitFlags", "SDL_INIT_(.*)").SetFlags(); |
||||
g.GenerateEnumFromMacros("Endianness", "SDL_(.*)_ENDIAN"); |
||||
g.GenerateEnumFromMacros("KeyState", "SDL_RELEASED", "SDL_PRESSED"); |
||||
|
||||
g.GenerateEnumFromMacros("AlphaState", "SDL_ALPHA_(.*)"); |
||||
|
||||
g.GenerateEnumFromMacros("HatState", "SDL_HAT_(.*)"); |
||||
|
||||
g.IgnoreModuleWithName("SDL_atomic*"); |
||||
g.IgnoreModuleWithName("SDL_endian*"); |
||||
g.IgnoreModuleWithName("SDL_main*"); |
||||
g.IgnoreModuleWithName("SDL_mutex*"); |
||||
g.IgnoreModuleWithName("SDL_stdinc*"); |
||||
|
||||
g.RemovePrefix("SDL_"); |
||||
g.RemovePrefix("SCANCODE_"); |
||||
g.RemovePrefix("SDLK_"); |
||||
g.RemovePrefix("KMOD_"); |
||||
g.RemovePrefix("LOG_CATEGORY_"); |
||||
|
||||
g.Process(); |
||||
|
||||
g.FindEnum("PIXELTYPE").Name = "PixelType"; |
||||
g.FindEnum("BITMAPORDER").Name = "BitmapOrder"; |
||||
g.FindEnum("PACKEDORDER").Name = "PackedOrder"; |
||||
g.FindEnum("ARRAYORDER").Name = "ArrayOrder"; |
||||
g.FindEnum("PACKEDLAYOUT").Name = "PackedLayout"; |
||||
g.FindEnum("PIXELFORMAT").Name = "PixelFormat"; |
||||
g.FindEnum("assert_state").Name = "AssertState"; |
||||
|
||||
//gen.FindEnum("LOG_CATEGORY").Name = "LogCategory";
|
||||
} |
||||
|
||||
public void Run(String[] args) |
||||
{ |
||||
options = new Options(); |
||||
|
||||
if (!ParseCommandLineOptions(args)) |
||||
return; |
||||
|
||||
library = new Library(options.OutputNamespace); |
||||
|
||||
ParseNativeHeaders(); |
||||
GenerateCode(); |
||||
} |
||||
|
||||
static void Main(String[] args) |
||||
{ |
||||
var program = new Program(); |
||||
program.Run(args); |
||||
|
||||
Console.ReadKey(); |
||||
} |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
using System.Reflection; |
||||
using System.Runtime.CompilerServices; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Generator")] |
||||
[assembly: AssemblyDescription("")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyCompany("Microsoft")] |
||||
[assembly: AssemblyProduct("Generator")] |
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2012")] |
||||
[assembly: AssemblyTrademark("")] |
||||
[assembly: AssemblyCulture("")] |
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)] |
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("16e665d1-888a-41e4-bb81-02075f7907b2")] |
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")] |
||||
[assembly: AssemblyFileVersion("1.0.0.0")] |
@ -0,0 +1,684 @@
@@ -0,0 +1,684 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 10.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Cxxi.Templates |
||||
{ |
||||
using System; |
||||
|
||||
|
||||
#line 1 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "10.0.0.0")] |
||||
public partial class CSharpModule : CSharpModuleBase |
||||
{ |
||||
public virtual string TransformText() |
||||
{ |
||||
this.Write("using System;\r\nusing System.Runtime.InteropServices;\r\n\r\nnamespace "); |
||||
|
||||
#line 6 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(SafeIdentifier(Library.Name))); |
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\r\n{\r\n"); |
||||
|
||||
#line 8 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
GenerateDeclarations(); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("}\r\n\r\n"); |
||||
return this.GenerationEnvironment.ToString(); |
||||
} |
||||
|
||||
#line 13 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateDeclarations() |
||||
{ |
||||
PushIndent(DefaultIndent); |
||||
|
||||
bool NeedsNewline = false; |
||||
|
||||
// Generate all the enum declarations for the module.
|
||||
for(int i = 0; i < Module.Global.Enums.Count; ++i) |
||||
{ |
||||
var E = Module.Global.Enums[i]; |
||||
if (E.Ignore) continue; |
||||
|
||||
GenerateEnum(E); |
||||
NeedsNewline = true; |
||||
if (i < Module.Global.Enums.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the struct/class declarations for the module.
|
||||
for(int i = 0; i < Module.Global.Classes.Count; ++i) |
||||
{ |
||||
var C = Module.Global.Classes[i]; |
||||
if (C.Ignore) continue; |
||||
|
||||
GenerateClass(C); |
||||
NeedsNewline = true; |
||||
if (i < Module.Global.Classes.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
if (Module.Global.HasFunctions) |
||||
{ |
||||
WriteLine("public partial class " + SafeIdentifier(Library.Name)); |
||||
WriteLine("{"); |
||||
PushIndent(DefaultIndent); |
||||
} |
||||
|
||||
// Generate all the function declarations for the module.
|
||||
foreach(var E in Module.Global.Functions) |
||||
{ |
||||
GenerateFunction(E); |
||||
} |
||||
|
||||
if (Module.Global.HasFunctions) |
||||
{ |
||||
PopIndent(); |
||||
WriteLine("}"); |
||||
} |
||||
|
||||
PopIndent(); |
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 75 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateTypeCommon(Declaration T) |
||||
{ |
||||
GenerateSummary(T.BriefComment); |
||||
GenerateDebug(T); |
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 83 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateClass(Class C) |
||||
{ |
||||
if(C.Ignore) return; |
||||
GenerateTypeCommon(C); |
||||
|
||||
Write("public "); |
||||
|
||||
if (C.IsAbstract) |
||||
Write("abstract "); |
||||
|
||||
Write("class {0}", C.Name); |
||||
|
||||
if (C.HasBase) |
||||
Write(" : {0}", C.Bases[0].Class.Name); |
||||
|
||||
WriteLine(String.Empty); |
||||
WriteLine("{"); |
||||
|
||||
PushIndent(DefaultIndent); |
||||
foreach(var F in C.Fields) |
||||
{ |
||||
GenerateTypeCommon(F); |
||||
WriteLine("public {0} {1};", F.Type, F.Name); |
||||
} |
||||
PopIndent(); |
||||
|
||||
WriteLine("}"); |
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 115 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateFunction(Function F) |
||||
{ |
||||
if(F.Ignore) return; |
||||
GenerateTypeCommon(F); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 120 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("[DllImport(\""); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 121 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(SafeIdentifier(Library.Name))); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 121 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(".dll\")]\r\npublic static extern "); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 122 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(F.ReturnType)); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 122 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(" "); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 122 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(SafeIdentifier(F.Name))); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 122 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("("); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 122 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
for(int i = 0; i < F.Parameters.Count; ++i) |
||||
{ |
||||
var P = F.Parameters[i]; |
||||
Write("{0} {1}", P.Type, SafeIdentifier(P.Name)); |
||||
if (i < F.Parameters.Count - 1) |
||||
Write(", "); |
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 130 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(");\r\n"); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 131 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
WriteLine(""); |
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 136 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateDebug(Declaration T) |
||||
{ |
||||
if(Options.OutputDebug && !String.IsNullOrWhiteSpace(T.DebugText)) |
||||
WriteLine("// DEBUG: " + T.DebugText); |
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 144 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateSummary(string Comment) |
||||
{ |
||||
if(String.IsNullOrWhiteSpace(Comment)) |
||||
return; |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 149 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("/// <summary>\r\n/// "); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 151 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(Comment)); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 151 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("\r\n/// </summary>\r\n"); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 153 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 157 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateInlineSummary(string Comment) |
||||
{ |
||||
if(String.IsNullOrWhiteSpace(Comment)) |
||||
return; |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 162 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("/// <summary> "); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 163 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(Comment)); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 163 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(" </summary>\r\n"); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 164 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 168 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
public void GenerateEnum(Enumeration E) |
||||
{ |
||||
if(E.Ignore) return; |
||||
GenerateTypeCommon(E); |
||||
|
||||
if(E.Modifiers.HasFlag(Enumeration.EnumModifiers.Flags)) |
||||
WriteLine("[Flags]"); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 176 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("public enum "); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 177 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(SafeIdentifier(E.Name))); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 177 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("\r\n"); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 178 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
if(E.Type.Type != PrimitiveType.Int32) |
||||
WriteLine(" : {0}", E.Type.Type.ConvertToTypeName()); |
||||
WriteLine("{"); |
||||
|
||||
PushIndent(DefaultIndent); |
||||
for(int i = 0; i < E.Items.Count; ++i) |
||||
{ |
||||
var I = E.Items[i]; |
||||
GenerateInlineSummary(I.Comment); |
||||
if (I.ExplicitValue) |
||||
Write(String.Format("{0} = {1}", SafeIdentifier(I.Name), I.Value)); |
||||
else |
||||
Write(String.Format("{0}", SafeIdentifier(I.Name))); |
||||
|
||||
if (i < E.Items.Count - 1) |
||||
WriteLine(","); |
||||
} |
||||
PopIndent(); |
||||
WriteLine(""); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 198 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
this.Write("}\r\n"); |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 200 "C:\Users\Tritonite\Development\cxxi\src\Generator\Templates\CSharpModule.tt"
|
||||
|
||||
} |
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
} |
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#region Base class
|
||||
/// <summary>
|
||||
/// Base class for this transformation
|
||||
/// </summary>
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "10.0.0.0")] |
||||
public class CSharpModuleBase |
||||
{ |
||||
#region Fields
|
||||
private global::System.Text.StringBuilder generationEnvironmentField; |
||||
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; |
||||
private global::System.Collections.Generic.List<int> indentLengthsField; |
||||
private string currentIndentField = ""; |
||||
private bool endsWithNewline; |
||||
private global::System.Collections.Generic.IDictionary<string, object> sessionField; |
||||
#endregion
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// The string builder that generation-time code is using to assemble generated output
|
||||
/// </summary>
|
||||
protected System.Text.StringBuilder GenerationEnvironment |
||||
{ |
||||
get |
||||
{ |
||||
if ((this.generationEnvironmentField == null)) |
||||
{ |
||||
this.generationEnvironmentField = new global::System.Text.StringBuilder(); |
||||
} |
||||
return this.generationEnvironmentField; |
||||
} |
||||
set |
||||
{ |
||||
this.generationEnvironmentField = value; |
||||
} |
||||
} |
||||
/// <summary>
|
||||
/// The error collection for the generation process
|
||||
/// </summary>
|
||||
public System.CodeDom.Compiler.CompilerErrorCollection Errors |
||||
{ |
||||
get |
||||
{ |
||||
if ((this.errorsField == null)) |
||||
{ |
||||
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); |
||||
} |
||||
return this.errorsField; |
||||
} |
||||
} |
||||
/// <summary>
|
||||
/// A list of the lengths of each indent that was added with PushIndent
|
||||
/// </summary>
|
||||
private System.Collections.Generic.List<int> indentLengths |
||||
{ |
||||
get |
||||
{ |
||||
if ((this.indentLengthsField == null)) |
||||
{ |
||||
this.indentLengthsField = new global::System.Collections.Generic.List<int>(); |
||||
} |
||||
return this.indentLengthsField; |
||||
} |
||||
} |
||||
/// <summary>
|
||||
/// Gets the current indent we use when adding lines to the output
|
||||
/// </summary>
|
||||
public string CurrentIndent |
||||
{ |
||||
get |
||||
{ |
||||
return this.currentIndentField; |
||||
} |
||||
} |
||||
/// <summary>
|
||||
/// Current transformation session
|
||||
/// </summary>
|
||||
public virtual global::System.Collections.Generic.IDictionary<string, object> Session |
||||
{ |
||||
get |
||||
{ |
||||
return this.sessionField; |
||||
} |
||||
set |
||||
{ |
||||
this.sessionField = value; |
||||
} |
||||
} |
||||
#endregion
|
||||
#region Transform-time helpers
|
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string textToAppend) |
||||
{ |
||||
if (string.IsNullOrEmpty(textToAppend)) |
||||
{ |
||||
return; |
||||
} |
||||
// If we're starting off, or if the previous text ended with a newline,
|
||||
// we have to append the current indent first.
|
||||
if (((this.GenerationEnvironment.Length == 0) |
||||
|| this.endsWithNewline)) |
||||
{ |
||||
this.GenerationEnvironment.Append(this.currentIndentField); |
||||
this.endsWithNewline = false; |
||||
} |
||||
// Check if the current text ends with a newline
|
||||
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) |
||||
{ |
||||
this.endsWithNewline = true; |
||||
} |
||||
// This is an optimization. If the current indent is "", then we don't have to do any
|
||||
// of the more complex stuff further down.
|
||||
if ((this.currentIndentField.Length == 0)) |
||||
{ |
||||
this.GenerationEnvironment.Append(textToAppend); |
||||
return; |
||||
} |
||||
// Everywhere there is a newline in the text, add an indent after it
|
||||
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); |
||||
// If the text ends with a newline, then we should strip off the indent added at the very end
|
||||
// because the appropriate indent will be added when the next time Write() is called
|
||||
if (this.endsWithNewline) |
||||
{ |
||||
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); |
||||
} |
||||
else |
||||
{ |
||||
this.GenerationEnvironment.Append(textToAppend); |
||||
} |
||||
} |
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string textToAppend) |
||||
{ |
||||
this.Write(textToAppend); |
||||
this.GenerationEnvironment.AppendLine(); |
||||
this.endsWithNewline = true; |
||||
} |
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string format, params object[] args) |
||||
{ |
||||
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); |
||||
} |
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string format, params object[] args) |
||||
{ |
||||
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); |
||||
} |
||||
/// <summary>
|
||||
/// Raise an error
|
||||
/// </summary>
|
||||
public void Error(string message) |
||||
{ |
||||
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); |
||||
error.ErrorText = message; |
||||
this.Errors.Add(error); |
||||
} |
||||
/// <summary>
|
||||
/// Raise a warning
|
||||
/// </summary>
|
||||
public void Warning(string message) |
||||
{ |
||||
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); |
||||
error.ErrorText = message; |
||||
error.IsWarning = true; |
||||
this.Errors.Add(error); |
||||
} |
||||
/// <summary>
|
||||
/// Increase the indent
|
||||
/// </summary>
|
||||
public void PushIndent(string indent) |
||||
{ |
||||
if ((indent == null)) |
||||
{ |
||||
throw new global::System.ArgumentNullException("indent"); |
||||
} |
||||
this.currentIndentField = (this.currentIndentField + indent); |
||||
this.indentLengths.Add(indent.Length); |
||||
} |
||||
/// <summary>
|
||||
/// Remove the last indent that was added with PushIndent
|
||||
/// </summary>
|
||||
public string PopIndent() |
||||
{ |
||||
string returnValue = ""; |
||||
if ((this.indentLengths.Count > 0)) |
||||
{ |
||||
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; |
||||
this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); |
||||
if ((indentLength > 0)) |
||||
{ |
||||
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); |
||||
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); |
||||
} |
||||
} |
||||
return returnValue; |
||||
} |
||||
/// <summary>
|
||||
/// Remove any indentation
|
||||
/// </summary>
|
||||
public void ClearIndent() |
||||
{ |
||||
this.indentLengths.Clear(); |
||||
this.currentIndentField = ""; |
||||
} |
||||
#endregion
|
||||
#region ToString Helpers
|
||||
/// <summary>
|
||||
/// Utility class to produce culture-oriented representation of an object as a string.
|
||||
/// </summary>
|
||||
public class ToStringInstanceHelper |
||||
{ |
||||
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; |
||||
/// <summary>
|
||||
/// Gets or sets format provider to be used by ToStringWithCulture method.
|
||||
/// </summary>
|
||||
public System.IFormatProvider FormatProvider |
||||
{ |
||||
get |
||||
{ |
||||
return this.formatProviderField ; |
||||
} |
||||
set |
||||
{ |
||||
if ((value != null)) |
||||
{ |
||||
this.formatProviderField = value; |
||||
} |
||||
} |
||||
} |
||||
/// <summary>
|
||||
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
|
||||
/// </summary>
|
||||
public string ToStringWithCulture(object objectToConvert) |
||||
{ |
||||
if ((objectToConvert == null)) |
||||
{ |
||||
throw new global::System.ArgumentNullException("objectToConvert"); |
||||
} |
||||
System.Type t = objectToConvert.GetType(); |
||||
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { |
||||
typeof(System.IFormatProvider)}); |
||||
if ((method == null)) |
||||
{ |
||||
return objectToConvert.ToString(); |
||||
} |
||||
else |
||||
{ |
||||
return ((string)(method.Invoke(objectToConvert, new object[] { |
||||
this.formatProviderField }))); |
||||
} |
||||
} |
||||
} |
||||
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); |
||||
public ToStringInstanceHelper ToStringHelper |
||||
{ |
||||
get |
||||
{ |
||||
return this.toStringHelperField; |
||||
} |
||||
} |
||||
#endregion
|
||||
} |
||||
#endregion
|
||||
} |
@ -0,0 +1,202 @@
@@ -0,0 +1,202 @@
|
||||
<#@ template debug="true" language="C#" #> |
||||
<#@ output extension=".cs" #> |
||||
using System; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace <#= SafeIdentifier(Library.Name) #> |
||||
{ |
||||
<# |
||||
GenerateDeclarations(); |
||||
#> |
||||
} |
||||
|
||||
<#+ |
||||
public void GenerateDeclarations() |
||||
{ |
||||
PushIndent(DefaultIndent); |
||||
|
||||
bool NeedsNewline = false; |
||||
|
||||
// Generate all the enum declarations for the module. |
||||
for(int i = 0; i < Module.Global.Enums.Count; ++i) |
||||
{ |
||||
var E = Module.Global.Enums[i]; |
||||
if (E.Ignore) continue; |
||||
|
||||
GenerateEnum(E); |
||||
NeedsNewline = true; |
||||
if (i < Module.Global.Enums.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the struct/class declarations for the module. |
||||
for(int i = 0; i < Module.Global.Classes.Count; ++i) |
||||
{ |
||||
var C = Module.Global.Classes[i]; |
||||
if (C.Ignore) continue; |
||||
|
||||
GenerateClass(C); |
||||
NeedsNewline = true; |
||||
if (i < Module.Global.Classes.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
if (Module.Global.HasFunctions) |
||||
{ |
||||
WriteLine("public partial class " + SafeIdentifier(Library.Name)); |
||||
WriteLine("{"); |
||||
PushIndent(DefaultIndent); |
||||
} |
||||
|
||||
// Generate all the function declarations for the module. |
||||
foreach(var E in Module.Global.Functions) |
||||
{ |
||||
GenerateFunction(E); |
||||
} |
||||
|
||||
if (Module.Global.HasFunctions) |
||||
{ |
||||
PopIndent(); |
||||
WriteLine("}"); |
||||
} |
||||
|
||||
PopIndent(); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateTypeCommon(CppType T) |
||||
{ |
||||
GenerateSummary(T.BriefComment); |
||||
GenerateDebug(T); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateClass(Class C) |
||||
{ |
||||
if(C.Ignore) return; |
||||
GenerateTypeCommon(C); |
||||
|
||||
Write("public "); |
||||
|
||||
if (C.IsAbstract) |
||||
Write("abstract "); |
||||
|
||||
Write("class {0}", C.Name); |
||||
|
||||
if (C.HasBase) |
||||
Write(" : {0}", C.Bases[0].Class.Name); |
||||
|
||||
WriteLine(String.Empty); |
||||
WriteLine("{"); |
||||
|
||||
PushIndent(DefaultIndent); |
||||
foreach(var F in C.Fields) |
||||
{ |
||||
GenerateTypeCommon(F); |
||||
WriteLine("public {0} {1};", F.Type, F.Name); |
||||
} |
||||
PopIndent(); |
||||
|
||||
WriteLine("}"); |
||||
} |
||||
#> |
||||
|
||||
|
||||
<#+ |
||||
public void GenerateFunction(Function F) |
||||
{ |
||||
if(F.Ignore) return; |
||||
GenerateTypeCommon(F); |
||||
#> |
||||
[DllImport("<#= SafeIdentifier(Library.Name) #>.dll")] |
||||
public static extern <#= F.ReturnType #> <#= SafeIdentifier(F.Name) #>(<#+ |
||||
for(int i = 0; i < F.Parameters.Count; ++i) |
||||
{ |
||||
var P = F.Parameters[i]; |
||||
Write("{0} {1}", P.Type, SafeIdentifier(P.Name)); |
||||
if (i < F.Parameters.Count - 1) |
||||
Write(", "); |
||||
} |
||||
#>); |
||||
<#+ |
||||
WriteLine(""); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateDebug(CppType T) |
||||
{ |
||||
if(Options.OutputDebug && !String.IsNullOrWhiteSpace(T.DebugText)) |
||||
WriteLine("// DEBUG: " + T.DebugText); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateSummary(string Comment) |
||||
{ |
||||
if(String.IsNullOrWhiteSpace(Comment)) |
||||
return; |
||||
#> |
||||
/// <summary> |
||||
/// <#= Comment #> |
||||
/// </summary> |
||||
<#+ |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateInlineSummary(string Comment) |
||||
{ |
||||
if(String.IsNullOrWhiteSpace(Comment)) |
||||
return; |
||||
#> |
||||
/// <summary> <#= Comment #> </summary> |
||||
<#+ |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateEnum(Enumeration E) |
||||
{ |
||||
if(E.Ignore) return; |
||||
GenerateTypeCommon(E); |
||||
|
||||
if(E.Modifiers.HasFlag(Enumeration.EnumModifiers.Flags)) |
||||
WriteLine("[Flags]"); |
||||
#> |
||||
public enum <#= SafeIdentifier(E.Name) #> |
||||
<#+ |
||||
if(E.Type.Type != PrimitiveType.Int32) |
||||
WriteLine(" : {0}", E.Type.Type.ConvertToTypeName()); |
||||
WriteLine("{"); |
||||
|
||||
PushIndent(DefaultIndent); |
||||
for(int i = 0; i < E.Items.Count; ++i) |
||||
{ |
||||
var I = E.Items[i]; |
||||
GenerateInlineSummary(I.Comment); |
||||
if (I.ExplicitValue) |
||||
Write(String.Format("{0} = {1}", SafeIdentifier(I.Name), I.Value)); |
||||
else |
||||
Write(String.Format("{0}", SafeIdentifier(I.Name))); |
||||
|
||||
if (i < E.Items.Count - 1) |
||||
WriteLine(","); |
||||
} |
||||
PopIndent(); |
||||
WriteLine(""); |
||||
#> |
||||
} |
||||
<#+ |
||||
} |
||||
#> |
@ -0,0 +1,177 @@
@@ -0,0 +1,177 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Text.RegularExpressions; |
||||
using System.Linq; |
||||
using System.Globalization; |
||||
using Cxxi; |
||||
|
||||
public abstract class Transformation |
||||
{ |
||||
public virtual bool ProcessType(Declaration type) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public virtual bool ProcessEnumItem(Enumeration.Item item) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public class RenameTransform : Transformation |
||||
{ |
||||
public string Pattern; |
||||
public string Replacement; |
||||
|
||||
public RenameTransform(string pattern, string replacement) |
||||
{ |
||||
Pattern = pattern; |
||||
Replacement = replacement; |
||||
} |
||||
|
||||
public override bool ProcessType(Declaration type) |
||||
{ |
||||
return Rename(ref type.Name); |
||||
} |
||||
|
||||
public override bool ProcessEnumItem(Enumeration.Item item) |
||||
{ |
||||
return Rename(ref item.Name); |
||||
} |
||||
|
||||
bool Rename(ref string name) |
||||
{ |
||||
string replace = Regex.Replace(name, Pattern, Replacement); |
||||
|
||||
if (!name.Equals(replace)) |
||||
{ |
||||
name = replace; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public partial class Generator |
||||
{ |
||||
public void RemovePrefix(string prefix) |
||||
{ |
||||
Transformations.Add(new RenameTransform(prefix, String.Empty)); |
||||
} |
||||
|
||||
public void RemoveType(Declaration type) |
||||
{ |
||||
|
||||
} |
||||
|
||||
public Enumeration FindEnum(string name) |
||||
{ |
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
var @enum = module.Global.FindEnumWithName(name); |
||||
if (@enum != null) |
||||
return @enum; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public Enumeration GetEnumWithMatchingItem(string Pattern) |
||||
{ |
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
Enumeration @enum = module.Global.FindEnumWithItem(Pattern); |
||||
if (@enum == null) continue; |
||||
return @enum; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public Module IgnoreModuleWithName(string Pattern) |
||||
{ |
||||
Module module = Library.Modules.Find( |
||||
m => Regex.Match(m.FilePath, Pattern).Success); |
||||
|
||||
if (module != null) |
||||
module.Ignore = true; |
||||
|
||||
return module; |
||||
} |
||||
|
||||
public void IgnoreEnumWithMatchingItem(string Pattern) |
||||
{ |
||||
Enumeration @enum = GetEnumWithMatchingItem(Pattern); |
||||
if (@enum != null) |
||||
@enum.Ignore = true; |
||||
} |
||||
|
||||
public void SetNameOfEnumWithMatchingItem(string Pattern, string Name) |
||||
{ |
||||
Enumeration @enum = GetEnumWithMatchingItem(Pattern); |
||||
if (@enum != null) |
||||
@enum.Name = Name; |
||||
} |
||||
|
||||
static bool ParseToNumber(string num, out long val) |
||||
{ |
||||
if (num.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase)) |
||||
{ |
||||
num = num.Substring(2); |
||||
|
||||
return long.TryParse(num, NumberStyles.HexNumber, |
||||
CultureInfo.CurrentCulture, out val); |
||||
} |
||||
|
||||
return long.TryParse(num, out val); |
||||
} |
||||
|
||||
static long ParseMacroExpression(string Expression) |
||||
{ |
||||
long val; |
||||
if (ParseToNumber(Expression, out val)) |
||||
return val; |
||||
// TODO: Handle string expressions
|
||||
return 0; |
||||
} |
||||
|
||||
public Enumeration.Item GenerateEnumItemFromMacro(MacroDefine macro) |
||||
{ |
||||
var item = new Enumeration.Item(); |
||||
item.Name = macro.Name; |
||||
item.Expression = macro.Expression; |
||||
item.Value = ParseMacroExpression(macro.Expression); |
||||
|
||||
return item; |
||||
} |
||||
|
||||
public Enumeration GenerateEnumFromMacros(string Name, params string[] Macros) |
||||
{ |
||||
Enumeration @enum = new Enumeration(); |
||||
@enum.Name = Name; |
||||
|
||||
var pattern = String.Join("|", Macros); |
||||
var regex = new Regex(pattern); |
||||
|
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
foreach (var macro in module.Macros) |
||||
{ |
||||
var match = regex.Match(macro.Name); |
||||
if (!match.Success) continue; |
||||
|
||||
var item = GenerateEnumItemFromMacro(macro); |
||||
@enum.AddItem(item); |
||||
} |
||||
|
||||
if (@enum.Items.Count > 0) |
||||
{ |
||||
module.Global.Enums.Add(@enum); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return @enum; |
||||
} |
||||
} |
Loading…
Reference in new issue