mirror of https://github.com/mono/CppSharp.git
Browse Source
- Removed reliance on T4 text templates that were proving to be a portability problem. - Refactored the generator design to make a little more sense. - Moved the examples to their own projects. - Improved the build system to only use one unified output folder. - Added much improved template support. - Added work-in-progress C++/CLI generator backend. - Added the concept of type maps.pull/1/head
67 changed files with 6506 additions and 2386 deletions
@ -1,34 +1,12 @@
@@ -1,34 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
||||
<Filter Include="src"> |
||||
<UniqueIdentifier>{254AD2D5-F792-C842-A59A-EFC933E51C60}</UniqueIdentifier> |
||||
</Filter> |
||||
<Filter Include="src\Parser"> |
||||
<UniqueIdentifier>{35E5E65B-7ABF-A54D-AEC8-338693EF5D27}</UniqueIdentifier> |
||||
</Filter> |
||||
<ClInclude Include="..\src\Parser\CXXABI.h" /> |
||||
<ClInclude Include="..\src\Parser\Interop.h" /> |
||||
<ClInclude Include="..\src\Parser\Parser.h" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<None Include="..\Parser.lua" /> |
||||
<None Include="..\premake4.lua" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ClInclude Include="..\..\src\Parser\CXXABI.h"> |
||||
<Filter>src\Parser</Filter> |
||||
</ClInclude> |
||||
<ClInclude Include="..\..\src\Parser\Interop.h"> |
||||
<Filter>src\Parser</Filter> |
||||
</ClInclude> |
||||
<ClInclude Include="..\..\src\Parser\Parser.h"> |
||||
<Filter>src\Parser</Filter> |
||||
</ClInclude> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ClCompile Include="..\..\src\Parser\Main.cpp"> |
||||
<Filter>src\Parser</Filter> |
||||
</ClCompile> |
||||
<ClCompile Include="..\..\src\Parser\Parser.cpp"> |
||||
<Filter>src\Parser</Filter> |
||||
</ClCompile> |
||||
<ClCompile Include="..\src\Parser\Main.cpp" /> |
||||
<ClCompile Include="..\src\Parser\Parser.cpp" /> |
||||
</ItemGroup> |
||||
</Project> |
||||
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
using Cxxi.Generators; |
||||
using Cxxi.Passes; |
||||
using Cxxi.Templates; |
||||
using Generator = Cxxi.Generators.Generator; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Transform the Clang library declarations to something more .NET friendly.
|
||||
/// </summary>
|
||||
class Clang : ILibrary |
||||
{ |
||||
public void Preprocess(LibraryHelpers g) |
||||
{ |
||||
//g.SetNameOfEnumWithMatchingItem("SDL_LOG_CATEGORY_CUSTOM", "LogCategory");
|
||||
|
||||
// Clean up types
|
||||
g.FindClass("CXString").IsOpaque = true; |
||||
g.FindClass("CXSourceLocation").IsOpaque = true; |
||||
g.FindClass("CXSourceRange").IsOpaque = true; |
||||
g.FindClass("CXCursor").IsOpaque = true; |
||||
g.FindClass("CXType").IsOpaque = true; |
||||
g.FindClass("CXToken").IsOpaque = true; |
||||
g.FindClass("CXIdxLoc").IsOpaque = true; |
||||
g.FindClass("CXTranslationUnitImpl").IsOpaque = true; |
||||
} |
||||
|
||||
public void Postprocess(LibraryHelpers g) |
||||
{ |
||||
g.FindEnum("CompletionContext").SetFlags(); |
||||
g.FindClass("String").Name = "CXString"; |
||||
//gen.SetNameOfEnumWithName("LOG_CATEGORY", "LogCategory");
|
||||
} |
||||
|
||||
public void Postprocess(Generators.Generator generator) |
||||
{ |
||||
|
||||
} |
||||
|
||||
public void SetupPasses(PassBuilder p) |
||||
{ |
||||
p.RemovePrefix("CX"); |
||||
p.RemovePrefix("clang_"); |
||||
p.RenameWithPattern("^_", string.Empty, RenameTargets.Any); |
||||
|
||||
// Clean up enums
|
||||
p.RemovePrefixEnumItem("ChildVisit_"); |
||||
p.RemovePrefixEnumItem("Comment_"); |
||||
p.RemovePrefixEnumItem("Availability_"); |
||||
p.RemovePrefixEnumItem("GlobalOpt_"); |
||||
p.RemovePrefixEnumItem("Diagnostic_"); |
||||
p.RemovePrefixEnumItem("LoadDiag_"); |
||||
p.RemovePrefixEnumItem("TranslationUnit_"); |
||||
p.RemovePrefixEnumItem("SaveTranslationUnit_"); |
||||
p.RemovePrefixEnumItem("SaveError_"); |
||||
p.RemovePrefixEnumItem("TranslationUnit_"); |
||||
p.RemovePrefixEnumItem("Reparse_"); |
||||
p.RemovePrefixEnumItem("TUResourceUsage_"); |
||||
p.RemovePrefixEnumItem("Cursor_"); |
||||
p.RemovePrefixEnumItem("Linkage_"); |
||||
p.RemovePrefixEnumItem("Language_"); |
||||
p.RemovePrefixEnumItem("Type_"); |
||||
p.RemovePrefixEnumItem("CallingConv_"); |
||||
p.RemovePrefixEnumItem("CommentInlineCommandRenderKind_"); |
||||
p.RemovePrefixEnumItem("CommentParamPassDirection_"); |
||||
p.RemovePrefixEnumItem("NameRange_"); |
||||
p.RemovePrefixEnumItem("Token_"); |
||||
p.RemovePrefixEnumItem("CompletionChunk_"); |
||||
p.RemovePrefixEnumItem("CodeComplete_"); |
||||
p.RemovePrefixEnumItem("CompletionContext_"); |
||||
p.RemovePrefixEnumItem("Visit_"); |
||||
p.RemovePrefixEnumItem("IdxEntity_"); |
||||
p.RemovePrefixEnumItem("IdxEntityLang_"); |
||||
p.RemovePrefixEnumItem("IdxAttr_"); |
||||
p.RemovePrefixEnumItem("IdxObjCContainer_"); |
||||
p.RemovePrefixEnumItem("IdxEntityRef_"); |
||||
p.RemovePrefixEnumItem("IndexOpt_"); |
||||
p.RemovePrefixEnumItem("IdxObjCContainer_"); |
||||
} |
||||
|
||||
public void GenerateStart(TextTemplate template) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public void GenerateAfterNamespaces(TextTemplate template) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
||||
<PropertyGroup> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
<ProjectGuid>{5439BC03-FA91-4D93-9EA0-4E550C1610F3}</ProjectGuid> |
||||
<OutputType>Library</OutputType> |
||||
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
<RootNamespace>Clang</RootNamespace> |
||||
<AssemblyName>Clang</AssemblyName> |
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
||||
<FileAlignment>512</FileAlignment> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||
<DebugSymbols>true</DebugSymbols> |
||||
<DebugType>full</DebugType> |
||||
<Optimize>false</Optimize> |
||||
<OutputPath>..\..\build\bin\</OutputPath> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||
<DebugType>pdbonly</DebugType> |
||||
<Optimize>true</Optimize> |
||||
<OutputPath>..\..\build\bin\</OutputPath> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<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="Clang.cs" /> |
||||
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="..\..\src\Bridge\Bridge.csproj"> |
||||
<Project>{6BEB8FA2-97AA-40B7-AB92-42F6EDDC4490}</Project> |
||||
<Name>Bridge</Name> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\..\src\Generator\Generator.csproj"> |
||||
<Project>{73499B8E-A6A4-42FF-AB8A-754CE2780777}</Project> |
||||
<Name>Generator</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,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("Clang")] |
||||
[assembly: AssemblyDescription("")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyCompany("")] |
||||
[assembly: AssemblyProduct("Clang")] |
||||
[assembly: AssemblyCopyright("Copyright © 2013")] |
||||
[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("e7c52cd3-e09e-43ba-91e4-82bc31315f7c")] |
||||
|
||||
// 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,141 @@
@@ -0,0 +1,141 @@
|
||||
using Cxxi.Generators; |
||||
using Cxxi.Generators.CLI; |
||||
using Cxxi.Passes; |
||||
using Cxxi.Types; |
||||
|
||||
namespace Cxxi.Libraries |
||||
{ |
||||
/// <summary>
|
||||
/// Transform the Flush library declarations to something more .NET friendly.
|
||||
/// </summary>
|
||||
class Flush : ILibrary |
||||
{ |
||||
public void Preprocess(LibraryHelpers g) |
||||
{ |
||||
g.IgnoreModulessWithName("API.h"); |
||||
g.IgnoreModulessWithName("Concurrency.h"); |
||||
g.IgnoreModulessWithName("ConcurrentQueue.h"); |
||||
g.IgnoreModulessWithName("Delegate.h"); |
||||
g.IgnoreModulessWithName("Event.h"); |
||||
g.IgnoreModulessWithName("Handle.h"); |
||||
//g.IgnoreModulessWithName("Memory.h");
|
||||
g.IgnoreModulessWithName("Object.h"); |
||||
g.IgnoreModulessWithName("Pointers.h"); |
||||
g.IgnoreModulessWithName("References.h"); |
||||
//g.IgnoreModulessWithName("Reflection.h");
|
||||
g.IgnoreModulessWithName("Serialization.h"); |
||||
|
||||
//Core
|
||||
g.SetClassAsValueType("StringHash"); |
||||
g.IgnoreClassWithName("RawStringCompare"); |
||||
|
||||
g.IgnoreFunctionWithName("LogCreate"); |
||||
g.SetClassAsValueType("LogEntry"); |
||||
g.SetClassAsValueType("FileWatchEvent"); |
||||
g.SetClassAsValueType("ExtensionMetadata"); |
||||
|
||||
g.IgnoreClassWithName("StreamFuncs"); |
||||
|
||||
// Math
|
||||
g.SetClassAsValueType("ColorP"); |
||||
g.SetClassAsValueType("Color"); |
||||
g.SetClassAsValueType("Vector2P"); |
||||
g.SetClassAsValueType("Vector2"); |
||||
g.SetClassAsValueType("Vector2i"); |
||||
g.SetClassAsValueType("Vector3P"); |
||||
g.SetClassAsValueType("Vector3"); |
||||
g.SetClassAsValueType("Vector4"); |
||||
g.SetClassAsValueType("EulerAngles"); |
||||
g.SetClassAsValueType("QuaternionP"); |
||||
g.SetClassAsValueType("Quaternion"); |
||||
|
||||
// Resources
|
||||
g.IgnoreFunctionWithName("ResourcesInitialize"); |
||||
g.IgnoreFunctionWithName("ResourcesDeinitialize"); |
||||
g.SetClassAsValueType("ResourceEvent"); |
||||
g.SetClassAsValueType("ResourceLoadOption"); |
||||
g.SetClassAsValueType("ResourceLoadOptions"); |
||||
|
||||
// Engine
|
||||
g.IgnoreClassMethodWithName("Engine", "addSubsystem"); |
||||
} |
||||
|
||||
public void Postprocess(LibraryHelpers generator) |
||||
{ |
||||
} |
||||
|
||||
public void SetupPasses(PassBuilder p) |
||||
{ |
||||
p.RenameDeclsCase(RenameTargets.Function | RenameTargets.Method | RenameTargets.Field, |
||||
RenameCasePattern.UpperCamelCase); |
||||
} |
||||
|
||||
public void GenerateStart(TextTemplate template) |
||||
{ |
||||
template.WriteLine("/************************************************************************"); |
||||
template.WriteLine("*"); |
||||
template.WriteLine("* Flood Project \u00A9 (2008-201x)"); |
||||
template.WriteLine("* Licensed under the simplified BSD license. All rights reserved."); |
||||
template.WriteLine("*"); |
||||
template.WriteLine("************************************************************************/"); |
||||
template.NewLine(); |
||||
if (template is CLISourcesTemplate) |
||||
template.WriteLine("#include \"_Marshal.h\""); |
||||
} |
||||
|
||||
public void GenerateAfterNamespaces(TextTemplate template) |
||||
{ |
||||
if (template is CLISourcesTemplate) |
||||
template.WriteLine("using namespace clix;"); |
||||
} |
||||
} |
||||
|
||||
namespace Types.Flush |
||||
{ |
||||
[TypeMap("RefPtr")] |
||||
public class RefPtr : TypeMap |
||||
{ |
||||
public override string Signature() |
||||
{ |
||||
var type = Type as TemplateSpecializationType; |
||||
return string.Format("{0}", type.Arguments[0].Type); |
||||
} |
||||
|
||||
public override string MarshalToNative(MarshalContext ctx) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public override string MarshalFromNative(MarshalContext ctx) |
||||
{ |
||||
return "nullptr"; |
||||
} |
||||
} |
||||
|
||||
[TypeMap("ResourceHandle")] |
||||
public class ResourceHandle : TypeMap |
||||
{ |
||||
public override string Signature() |
||||
{ |
||||
return "uint"; |
||||
} |
||||
|
||||
public override string MarshalToNative(MarshalContext ctx) |
||||
{ |
||||
return string.Format("(HandleId){0}", ctx.Parameter.Name); |
||||
} |
||||
|
||||
public override string MarshalFromNative(MarshalContext ctx) |
||||
{ |
||||
return string.Format("(HandleId){0}", ctx.ReturnVarName); |
||||
} |
||||
} |
||||
|
||||
[TypeMap("Path")] |
||||
[TypeMap("String")] |
||||
[TypeMap("StringWide")] |
||||
public class String : Cxxi.Types.Std.String |
||||
{ |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
||||
<PropertyGroup> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
<ProjectGuid>{28455425-1A80-458E-952C-5B0069866AAD}</ProjectGuid> |
||||
<OutputType>Library</OutputType> |
||||
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
<RootNamespace>Flood</RootNamespace> |
||||
<AssemblyName>Flood</AssemblyName> |
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
||||
<FileAlignment>512</FileAlignment> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||
<DebugSymbols>true</DebugSymbols> |
||||
<DebugType>full</DebugType> |
||||
<Optimize>false</Optimize> |
||||
<OutputPath>..\..\build\bin\</OutputPath> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||
<DebugType>pdbonly</DebugType> |
||||
<Optimize>true</Optimize> |
||||
<OutputPath>..\..\build\bin\</OutputPath> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<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="Flood.cs" /> |
||||
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="..\..\src\Bridge\Bridge.csproj"> |
||||
<Project>{6BEB8FA2-97AA-40B7-AB92-42F6EDDC4490}</Project> |
||||
<Name>Bridge</Name> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\..\src\Generator\Generator.csproj"> |
||||
<Project>{73499b8e-a6a4-42ff-ab8a-754ce2780777}</Project> |
||||
<Name>Generator</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,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("Flood")] |
||||
[assembly: AssemblyDescription("")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyCompany("")] |
||||
[assembly: AssemblyProduct("Flood")] |
||||
[assembly: AssemblyCopyright("Copyright © 2013")] |
||||
[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("e9efb51b-baab-4008-8924-47c33761bf0f")] |
||||
|
||||
// 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,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("SDL")] |
||||
[assembly: AssemblyDescription("")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyCompany("")] |
||||
[assembly: AssemblyProduct("SDL")] |
||||
[assembly: AssemblyCopyright("Copyright © 2013")] |
||||
[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("5934cefb-a2b3-4556-901b-4d512f28aecc")] |
||||
|
||||
// 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,74 @@
@@ -0,0 +1,74 @@
|
||||
using Cxxi.Generators; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Transform the SDL library declarations to something more .NET friendly.
|
||||
/// </summary>
|
||||
class SDL : ILibrary |
||||
{ |
||||
public void Preprocess(LibraryHelpers g) |
||||
{ |
||||
g.IgnoreEnumWithMatchingItem("SDL_FALSE"); |
||||
g.IgnoreEnumWithMatchingItem("DUMMY_ENUM_VALUE"); |
||||
|
||||
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("InputState", "SDL_RELEASED", "SDL_PRESSED"); |
||||
|
||||
g.GenerateEnumFromMacros("AlphaState", "SDL_ALPHA_(.*)"); |
||||
|
||||
g.GenerateEnumFromMacros("HatState", "SDL_HAT_(.*)"); |
||||
|
||||
g.IgnoreModulessWithName("SDL_atomic*"); |
||||
g.IgnoreModulessWithName("SDL_endian*"); |
||||
g.IgnoreModulessWithName("SDL_main*"); |
||||
g.IgnoreModulessWithName("SDL_mutex*"); |
||||
g.IgnoreModulessWithName("SDL_stdinc*"); |
||||
|
||||
//g.IgnoreModuleWithName("SDL_error");
|
||||
|
||||
g.IgnoreEnumWithMatchingItem("SDL_ENOMEM"); |
||||
g.IgnoreFunctionWithName("SDL_Error"); |
||||
} |
||||
|
||||
public void Postprocess(LibraryHelpers generator) |
||||
{ |
||||
generator.SetNameOfEnumWithName("PIXELTYPE", "PixelType"); |
||||
generator.SetNameOfEnumWithName("BITMAPORDER", "BitmapOrder"); |
||||
generator.SetNameOfEnumWithName("PACKEDORDER", "PackedOrder"); |
||||
generator.SetNameOfEnumWithName("ARRAYORDER", "ArrayOrder"); |
||||
generator.SetNameOfEnumWithName("PACKEDLAYOUT", "PackedLayout"); |
||||
generator.SetNameOfEnumWithName("PIXELFORMAT", "PixelFormats"); |
||||
generator.SetNameOfEnumWithName("assert_state", "AssertState"); |
||||
generator.SetClassBindName("assert_data", "AssertData"); |
||||
generator.SetNameOfEnumWithName("eventaction", "EventAction"); |
||||
|
||||
//gen.SetNameOfEnumWithName("LOG_CATEGORY", "LogCategory");
|
||||
} |
||||
|
||||
public void SetupPasses(PassBuilder p) |
||||
{ |
||||
p.RemovePrefix("SDL_"); |
||||
p.RemovePrefix("SCANCODE_"); |
||||
p.RemovePrefix("SDLK_"); |
||||
p.RemovePrefix("KMOD_"); |
||||
p.RemovePrefix("LOG_CATEGORY_"); |
||||
} |
||||
|
||||
public void GenerateStart(TextTemplate template) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public void GenerateAfterNamespaces(TextTemplate template) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
||||
<PropertyGroup> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
<ProjectGuid>{8D642354-FBD5-4551-95A6-09D369B83167}</ProjectGuid> |
||||
<OutputType>Library</OutputType> |
||||
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
<RootNamespace>SDL</RootNamespace> |
||||
<AssemblyName>SDL</AssemblyName> |
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
||||
<FileAlignment>512</FileAlignment> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||
<DebugSymbols>true</DebugSymbols> |
||||
<DebugType>full</DebugType> |
||||
<Optimize>false</Optimize> |
||||
<OutputPath>..\..\build\bin\</OutputPath> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||
<DebugType>pdbonly</DebugType> |
||||
<Optimize>true</Optimize> |
||||
<OutputPath>bin\</OutputPath> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<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="Properties\AssemblyInfo.cs" /> |
||||
<Compile Include="SDL.cs" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="..\..\src\Bridge\Bridge.csproj"> |
||||
<Project>{6BEB8FA2-97AA-40B7-AB92-42F6EDDC4490}</Project> |
||||
<Name>Bridge</Name> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\..\src\Generator\Generator.csproj"> |
||||
<Project>{73499B8E-A6A4-42FF-AB8A-754CE2780777}</Project> |
||||
<Name>Generator</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> |
||||
@ -1,59 +1,123 @@
@@ -1,59 +1,123 @@
|
||||
namespace Cxxi |
||||
using System; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a C++ declaration.
|
||||
/// </summary>
|
||||
public class Declaration |
||||
{ |
||||
// Name of the type.
|
||||
public string Name; |
||||
|
||||
// Doxygen-style brief comment.
|
||||
public string BriefComment; |
||||
|
||||
// Namespace the type is declared in.
|
||||
//public Namespace Namespace;
|
||||
|
||||
// Wether the type should be ignored.
|
||||
public bool Ignore; |
||||
|
||||
// Contains a debug text of the type declaration.
|
||||
public string DebugText; |
||||
|
||||
public Declaration() |
||||
{ |
||||
} |
||||
|
||||
public Declaration(string name) |
||||
{ |
||||
Name = name; |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return Name; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a type definition in C++.
|
||||
/// </summary>
|
||||
public class Typedef : Declaration |
||||
{ |
||||
/// Type defined.
|
||||
public Type Type; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C preprocessor macro definition.
|
||||
/// </summary>
|
||||
public class MacroDefine : Declaration |
||||
{ |
||||
// Contains the macro definition text.
|
||||
public string Expression; |
||||
|
||||
public MacroDefine() |
||||
{ |
||||
} |
||||
} |
||||
/// <summary>
|
||||
/// Represents a C++ declaration.
|
||||
/// </summary>
|
||||
public abstract class Declaration |
||||
{ |
||||
// Namespace the declaration is contained in.
|
||||
public Namespace Namespace; |
||||
|
||||
private string name; |
||||
|
||||
// Name of the declaration.
|
||||
public string Name |
||||
{ |
||||
get { return name; } |
||||
set |
||||
{ |
||||
name = value; |
||||
if (string.IsNullOrEmpty(OriginalName)) |
||||
OriginalName = name; |
||||
} |
||||
} |
||||
|
||||
// Name of the declaration.
|
||||
public string OriginalName; |
||||
|
||||
public string QualifiedOriginalName |
||||
{ |
||||
get |
||||
{ |
||||
return Namespace.IsRoot ? OriginalName |
||||
: string.Format("{0}::{1}", Namespace.Name, OriginalName); |
||||
} |
||||
} |
||||
|
||||
// Doxygen-style brief comment.
|
||||
public string BriefComment; |
||||
|
||||
// Whether the declaration should be ignored.
|
||||
public virtual bool Ignore |
||||
{ |
||||
get |
||||
{ |
||||
return ExplicityIgnored || Namespace.Ignore; |
||||
} |
||||
} |
||||
|
||||
// Whether the declaration was explicitly ignored.
|
||||
public bool ExplicityIgnored; |
||||
|
||||
// Contains debug text about the declaration.
|
||||
public string DebugText; |
||||
|
||||
// True if the declaration is incomplete (no definition).
|
||||
public bool IsIncomplete; |
||||
|
||||
protected Declaration() |
||||
{ |
||||
} |
||||
|
||||
protected Declaration(string name) |
||||
{ |
||||
Name = name; |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return OriginalName; |
||||
} |
||||
|
||||
public abstract T Visit<T>(IDeclVisitor<T> visitor); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a type definition in C++.
|
||||
/// </summary>
|
||||
public class TypedefDecl : Declaration |
||||
{ |
||||
/// Type defined.
|
||||
public Type Type; |
||||
|
||||
public override T Visit<T>(IDeclVisitor<T> visitor) |
||||
{ |
||||
return visitor.VisitTypedefDecl(this); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C preprocessor macro definition.
|
||||
/// </summary>
|
||||
public class MacroDefinition : Declaration |
||||
{ |
||||
// Contains the macro definition text.
|
||||
public string Expression; |
||||
|
||||
public MacroDefinition() |
||||
{ |
||||
} |
||||
|
||||
public override T Visit<T>(IDeclVisitor<T> visitor) |
||||
{ |
||||
return visitor.VisitMacroDefinition(this); |
||||
} |
||||
} |
||||
|
||||
public interface IDeclVisitor<out T> |
||||
{ |
||||
T VisitDeclaration(Declaration decl); |
||||
T VisitClassDecl(Class @class); |
||||
T VisitFieldDecl(Field field); |
||||
T VisitFunctionDecl(Function function); |
||||
T VisitMethodDecl(Method method); |
||||
T VisitParameterDecl(Parameter parameter); |
||||
T VisitTypedefDecl(TypedefDecl typedef); |
||||
T VisitEnumDecl(Enumeration @enum); |
||||
T VisitClassTemplateDecl(ClassTemplate template); |
||||
T VisitFunctionTemplateDecl(FunctionTemplate template); |
||||
T VisitMacroDefinition(MacroDefinition macro); |
||||
} |
||||
} |
||||
@ -1,23 +1,30 @@
@@ -1,23 +1,30 @@
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a field in a C/C++ record declaration.
|
||||
/// </summary>
|
||||
public class Field : Declaration |
||||
{ |
||||
public Type Type; |
||||
public AccessSpecifier Access; |
||||
public uint Offset = 0; |
||||
/// <summary>
|
||||
/// Represents a a C/C++ record field Decl.
|
||||
/// </summary>
|
||||
public class Field : Declaration |
||||
{ |
||||
public Type Type { get; set; } |
||||
public AccessSpecifier Access { get; set; } |
||||
public uint Offset { get; set; } |
||||
|
||||
public Field() |
||||
{ |
||||
} |
||||
public Field() |
||||
{ |
||||
Offset = 0; |
||||
} |
||||
|
||||
public Field(string name, Type type, AccessSpecifier access) |
||||
{ |
||||
Name = name; |
||||
Type = type; |
||||
Access = access; |
||||
} |
||||
} |
||||
public Field(string name, Type type, AccessSpecifier access) |
||||
{ |
||||
Name = name; |
||||
Type = type; |
||||
Access = access; |
||||
Offset = 0; |
||||
} |
||||
|
||||
public override T Visit<T>(IDeclVisitor<T> visitor) |
||||
{ |
||||
return visitor.VisitFieldDecl(this); |
||||
} |
||||
} |
||||
} |
||||
@ -1,104 +1,114 @@
@@ -1,104 +1,114 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
public enum CppAbi |
||||
{ |
||||
Itanium, |
||||
Microsoft, |
||||
ARM |
||||
} |
||||
|
||||
public enum InlineMethods |
||||
{ |
||||
Present, |
||||
Unavailable |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A module represents a parsed C++ translation unit.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("File = {FileName}, Ignored = {Ignore}")] |
||||
public class Module : Namespace |
||||
{ |
||||
public Module(string file) |
||||
{ |
||||
Macros = new List<MacroDefine>(); |
||||
FilePath = file; |
||||
Ignore = false; |
||||
} |
||||
|
||||
/// Contains the macros present in the unit.
|
||||
public List<MacroDefine> Macros; |
||||
|
||||
/// If the module should be ignored.
|
||||
public bool Ignore; |
||||
|
||||
/// Contains the path to the file.
|
||||
public string FilePath; |
||||
|
||||
/// Contains the name of the file.
|
||||
public string FileName |
||||
{ |
||||
get { return Path.GetFileName(FilePath); } |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A library contains all the modules.
|
||||
/// </summary>
|
||||
public class Library |
||||
{ |
||||
public string Name; |
||||
public string Native; |
||||
public List<Module> Modules; |
||||
|
||||
public Library(string name, string native) |
||||
{ |
||||
Name = name; |
||||
Native = native; |
||||
Modules = new List<Module>(); |
||||
} |
||||
|
||||
/// Finds an existing module or creates a new one given a file path.
|
||||
public Module FindOrCreateModule(string file) |
||||
{ |
||||
var module = Modules.Find(m => m.FilePath.Equals(file)); |
||||
|
||||
if (module == null) |
||||
{ |
||||
module = new Module(file); |
||||
Modules.Add(module); |
||||
} |
||||
|
||||
return module; |
||||
} |
||||
|
||||
/// Finds an existing enum in the library modules.
|
||||
public Enumeration FindEnum(string name) |
||||
{ |
||||
foreach (var module in Modules) |
||||
{ |
||||
var type = module.FindEnum(name); |
||||
if (type != null) return type; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/// Finds an existing struct/class in the library modules.
|
||||
public Class FindClass(string name, bool create = false) |
||||
{ |
||||
foreach (var module in Modules) |
||||
{ |
||||
var type = module.FindClass(name, create); |
||||
if (type != null) return type; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
||||
public enum CppAbi |
||||
{ |
||||
Itanium, |
||||
Microsoft, |
||||
ARM |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a parsed C++ unit.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("File = {FileName}, Ignored = {Ignore}")] |
||||
public class TranslationUnit : Namespace |
||||
{ |
||||
public TranslationUnit(string file) |
||||
{ |
||||
ForwardReferences = new List<Declaration>(); |
||||
Macros = new List<MacroDefinition>(); |
||||
FilePath = file; |
||||
} |
||||
|
||||
/// Forward reference declarations.
|
||||
public List<Declaration> ForwardReferences; |
||||
|
||||
/// Contains the macros present in the unit.
|
||||
public List<MacroDefinition> Macros; |
||||
|
||||
/// If the module should be ignored.
|
||||
public override bool Ignore |
||||
{ |
||||
get { return ExplicityIgnored; } |
||||
} |
||||
|
||||
public bool IsSystemHeader { get; set; } |
||||
|
||||
/// Contains the path to the file.
|
||||
public string FilePath; |
||||
|
||||
/// Contains the name of the file.
|
||||
public string FileName |
||||
{ |
||||
get { return Path.GetFileName(FilePath); } |
||||
} |
||||
|
||||
/// Contains the name of the module.
|
||||
public string FileNameWithoutExtension |
||||
{ |
||||
get { return Path.GetFileNameWithoutExtension(FileName); } |
||||
} |
||||
|
||||
/// Contains the include path.
|
||||
public string IncludePath; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A library contains all the modules.
|
||||
/// </summary>
|
||||
public class Library |
||||
{ |
||||
public string Name; |
||||
public string Native; |
||||
public List<TranslationUnit> TranslationUnits; |
||||
|
||||
public Library(string name, string native) |
||||
{ |
||||
Name = name; |
||||
Native = native; |
||||
TranslationUnits = new List<TranslationUnit>(); |
||||
} |
||||
|
||||
/// Finds an existing module or creates a new one given a file path.
|
||||
public TranslationUnit FindOrCreateModule(string file) |
||||
{ |
||||
var module = TranslationUnits.Find(m => m.FilePath.Equals(file)); |
||||
|
||||
if (module == null) |
||||
{ |
||||
module = new TranslationUnit(file); |
||||
TranslationUnits.Add(module); |
||||
} |
||||
|
||||
return module; |
||||
} |
||||
|
||||
/// Finds an existing enum in the library modules.
|
||||
public Enumeration FindEnum(string name) |
||||
{ |
||||
foreach (var module in TranslationUnits) |
||||
{ |
||||
var type = module.FindEnum(name); |
||||
if (type != null) return type; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/// Finds an existing struct/class in the library modules.
|
||||
public Class FindClass(string name, bool create = false) |
||||
{ |
||||
foreach (var module in TranslationUnits) |
||||
{ |
||||
var type = module.FindClass(name, create); |
||||
if (type != null) return type; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -1,26 +1,94 @@
@@ -1,26 +1,94 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a C++ method.
|
||||
/// </summary>
|
||||
public class Method : Function |
||||
{ |
||||
|
||||
public Method() |
||||
{ |
||||
} |
||||
|
||||
public AccessSpecifier Access { get; set; } |
||||
|
||||
public bool IsVirtual { get; set; } |
||||
public bool IsStatic { get; set; } |
||||
public bool IsConst { get; set; } |
||||
public bool IsArtificial { get; set; } |
||||
public bool IsConstructor { get; set; } |
||||
public bool IsDestructor { get; set; } |
||||
public bool IsCopyCtor { get; set; } |
||||
} |
||||
public enum CXXMethodKind |
||||
{ |
||||
Normal, |
||||
Constructor, |
||||
Destructor, |
||||
Conversion, |
||||
Operator, |
||||
UsingDirective |
||||
} |
||||
|
||||
public enum CXXOperatorKind |
||||
{ |
||||
None, |
||||
New, |
||||
Delete, |
||||
Array_New, |
||||
Array_Delete, |
||||
Plus, |
||||
Minus, |
||||
Star, |
||||
Slash, |
||||
Percent, |
||||
Caret, |
||||
Amp, |
||||
Pipe, |
||||
Tilde, |
||||
Exclaim, |
||||
Equal, |
||||
Less, |
||||
Greater, |
||||
PlusEqual, |
||||
MinusEqual, |
||||
StarEqual, |
||||
SlashEqual, |
||||
PercentEqual, |
||||
CaretEqual, |
||||
AmpEqual, |
||||
PipeEqual, |
||||
LessLess, |
||||
GreaterGreater, |
||||
LessLessEqual, |
||||
GreaterGreaterEqual, |
||||
EqualEqual, |
||||
ExclaimEqual, |
||||
LessEqual, |
||||
GreaterEqual, |
||||
AmpAmp, |
||||
PipePipe, |
||||
PlusPlus, |
||||
MinusMinus, |
||||
Comma, |
||||
ArrowStar, |
||||
Arrow, |
||||
Call, |
||||
Subscript, |
||||
Conditional |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ record method declaration.
|
||||
/// </summary>
|
||||
public class Method : Function |
||||
{ |
||||
public Method() |
||||
{ |
||||
} |
||||
|
||||
public AccessSpecifier Access { get; set; } |
||||
|
||||
public bool IsVirtual { get; set; } |
||||
public bool IsStatic { get; set; } |
||||
public bool IsConst { get; set; } |
||||
public bool IsImplicit { get; set; } |
||||
|
||||
public CXXMethodKind Kind; |
||||
public CXXOperatorKind OperatorKind; |
||||
|
||||
public bool IsConstructor |
||||
{ |
||||
get { return Kind == CXXMethodKind.Constructor; } |
||||
} |
||||
|
||||
public bool IsDestructor |
||||
{ |
||||
get { return Kind == CXXMethodKind.Destructor; } |
||||
} |
||||
|
||||
public bool IsDefaultConstructor; |
||||
public bool IsCopyConstructor; |
||||
public bool IsMoveConstructor; |
||||
} |
||||
} |
||||
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
using System.Collections.Generic; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
public struct TemplateParameter |
||||
{ |
||||
public string Name; |
||||
} |
||||
|
||||
public abstract class Template : Declaration |
||||
{ |
||||
protected Template(Declaration decl) |
||||
{ |
||||
TemplatedDecl = decl; |
||||
} |
||||
|
||||
public Declaration TemplatedDecl; |
||||
|
||||
public List<TemplateParameter> Parameters; |
||||
} |
||||
|
||||
public class ClassTemplate : Template |
||||
{ |
||||
public ClassTemplate(Declaration decl) |
||||
: base(decl) |
||||
{ |
||||
} |
||||
|
||||
public Class TemplatedClass |
||||
{ |
||||
get { return TemplatedDecl as Class; } |
||||
} |
||||
|
||||
public override T Visit<T>(IDeclVisitor<T> visitor) |
||||
{ |
||||
return visitor.VisitClassTemplateDecl(this); |
||||
} |
||||
} |
||||
|
||||
public class FunctionTemplate : Template |
||||
{ |
||||
public FunctionTemplate(Declaration decl) |
||||
: base(decl) |
||||
{ |
||||
} |
||||
|
||||
public Function TemplatedFunction |
||||
{ |
||||
get { return TemplatedDecl as Function; } |
||||
} |
||||
|
||||
public override T Visit<T>(IDeclVisitor<T> visitor) |
||||
{ |
||||
return visitor.VisitFunctionTemplateDecl(this); |
||||
} |
||||
} |
||||
} |
||||
@ -1,378 +1,395 @@
@@ -1,378 +1,395 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
public interface TypeTransform |
||||
{ |
||||
void TransformType(Type type); |
||||
void TransformTagType(TagType tag); |
||||
void TransformArrayType(ArrayType array); |
||||
void TransformFunctionType(FunctionType function); |
||||
void TransformPointerType(PointerType pointer); |
||||
void TransformBuiltinType(BuiltinType builtin); |
||||
void TransformTypedefType (TypedefType typedef); |
||||
void TransformDeclaration(Declaration declaration); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ type reference.
|
||||
/// </summary>
|
||||
public abstract class Type |
||||
{ |
||||
public Type() |
||||
{ |
||||
} |
||||
|
||||
public bool IsPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
var builtin = this as BuiltinType; |
||||
if (builtin != null) |
||||
return builtin.Type == primitive; |
||||
return false; |
||||
} |
||||
|
||||
public bool IsPointerToPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
var ptr = this as PointerType; |
||||
if (ptr == null) |
||||
return false; |
||||
return ptr.Pointee.IsPrimitiveType(primitive); |
||||
} |
||||
|
||||
public bool IsPointerTo<T>(out T type) where T : Type |
||||
{ |
||||
var ptr = this as PointerType; |
||||
|
||||
if (ptr == null) |
||||
{ |
||||
type = null; |
||||
return false; |
||||
} |
||||
|
||||
type = ptr.Pointee as T; |
||||
return type != null; |
||||
} |
||||
|
||||
public virtual void Transform(TypeTransform transform) |
||||
{ |
||||
transform.TransformType(this); |
||||
} |
||||
|
||||
// Converts the type to a C# type.
|
||||
public abstract string ToCSharp(); |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return ToCSharp(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ tag type reference.
|
||||
/// </summary>
|
||||
public class TagType : Type |
||||
{ |
||||
public TagType() |
||||
{ |
||||
} |
||||
|
||||
public Declaration Declaration; |
||||
|
||||
public override string ToCSharp() |
||||
{ |
||||
if (Declaration == null) |
||||
return string.Empty; |
||||
return Declaration.Name; |
||||
} |
||||
|
||||
public override void Transform(TypeTransform transform) |
||||
{ |
||||
transform.TransformTagType(this); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an C/C++ array type.
|
||||
/// </summary>
|
||||
public class ArrayType : Type |
||||
{ |
||||
public enum ArraySize |
||||
{ |
||||
Constant, |
||||
Variable |
||||
} |
||||
|
||||
public ArrayType() |
||||
{ |
||||
} |
||||
|
||||
// Type of the array elements.
|
||||
public Type Type; |
||||
|
||||
// Size type of array.
|
||||
public ArraySize SizeType; |
||||
|
||||
// In case of a constant size array.
|
||||
public long Size; |
||||
|
||||
public override string ToCSharp() |
||||
{ |
||||
// C# only supports fixed arrays in unsafe sections
|
||||
// and they are constrained to a set of built-in types.
|
||||
|
||||
return string.Format("{0}[]", Type); |
||||
} |
||||
|
||||
public override void Transform(TypeTransform transform) |
||||
{ |
||||
Type.Transform(transform); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an C/C++ function type.
|
||||
/// </summary>
|
||||
public class FunctionType : Type |
||||
{ |
||||
// Return type of the function.
|
||||
public Type ReturnType; |
||||
|
||||
// Argument types.
|
||||
public List<Type> Arguments; |
||||
|
||||
public FunctionType() |
||||
{ |
||||
Arguments = new List<Type>(); |
||||
} |
||||
|
||||
public override string ToCSharp() |
||||
{ |
||||
string args = string.Empty; |
||||
|
||||
if (Arguments.Count > 0) |
||||
args = ToArgumentString(); |
||||
|
||||
if (ReturnType.IsPrimitiveType(PrimitiveType.Void)) |
||||
{ |
||||
if (!string.IsNullOrEmpty(args)) |
||||
args = string.Format("<{0}>", args); |
||||
return string.Format("Action{0}", args); |
||||
} |
||||
|
||||
if (!string.IsNullOrEmpty(args)) |
||||
args = string.Format(", {0}", args); |
||||
|
||||
return string.Format("Func<{0}{1}>", |
||||
ReturnType.ToCSharp(), args); |
||||
} |
||||
|
||||
public string ToArgumentString() |
||||
{ |
||||
var s = string.Empty; |
||||
|
||||
for (int i = 0; i < Arguments.Count; ++i) |
||||
{ |
||||
var arg = Arguments[i]; |
||||
s += arg.ToCSharp(); |
||||
if (i < Arguments.Count - 1) |
||||
s += ", "; |
||||
} |
||||
|
||||
return s; |
||||
} |
||||
|
||||
public string ToDelegateString() |
||||
{ |
||||
return string.Format("delegate {0} {{0}}({1})", |
||||
ReturnType.ToCSharp(), ToArgumentString()); |
||||
} |
||||
|
||||
public override void Transform(TypeTransform transform) |
||||
{ |
||||
ReturnType.Transform(transform); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ pointer/reference type.
|
||||
/// </summary>
|
||||
public class PointerType : Type |
||||
{ |
||||
public PointerType() |
||||
{ |
||||
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents the modifiers on a C++ type reference.
|
||||
/// </summary>
|
||||
public enum TypeModifier |
||||
{ |
||||
Value, |
||||
Pointer, |
||||
// L-value references
|
||||
LVReference, |
||||
// R-value references
|
||||
RVReference |
||||
} |
||||
|
||||
static string ConvertModifierToString(TypeModifier modifier) |
||||
{ |
||||
switch (modifier) |
||||
{ |
||||
case TypeModifier.Value: return string.Empty; |
||||
case TypeModifier.Pointer: |
||||
case TypeModifier.LVReference: |
||||
case TypeModifier.RVReference: return "*"; |
||||
} |
||||
|
||||
return string.Empty; |
||||
} |
||||
|
||||
public Type Pointee; |
||||
|
||||
public TypeModifier Modifier; |
||||
|
||||
public override string ToCSharp() |
||||
{ |
||||
if (Pointee is FunctionType) |
||||
{ |
||||
var function = Pointee as FunctionType; |
||||
return function.ToCSharp(); |
||||
} |
||||
|
||||
if (Pointee is TagType) |
||||
return Pointee.ToCSharp(); |
||||
|
||||
return "IntPtr"; |
||||
|
||||
//return string.Format("{0}{1}",
|
||||
// Pointee.ToCSharp(), ConvertModifierToString(Modifier));
|
||||
} |
||||
|
||||
public override void Transform(TypeTransform transform) |
||||
{ |
||||
Pointee.Transform(transform); |
||||
} |
||||
} |
||||
|
||||
public class TypedefType : Type |
||||
{ |
||||
public TypedefType() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public Declaration Declaration; |
||||
|
||||
public override void Transform(TypeTransform transform) |
||||
{ |
||||
transform.TransformTypedefType(this); |
||||
} |
||||
|
||||
public override string ToCSharp() |
||||
{ |
||||
return Declaration.Name; |
||||
} |
||||
} |
||||
|
||||
#region Primitives
|
||||
|
||||
/// <summary>
|
||||
/// Represents the C++ built-in types.
|
||||
/// </summary>
|
||||
public enum PrimitiveType |
||||
{ |
||||
Null, |
||||
Void, |
||||
Bool, |
||||
WideChar, |
||||
Int8, |
||||
UInt8, |
||||
Int16, |
||||
UInt16, |
||||
Int32, |
||||
UInt32, |
||||
Int64, |
||||
UInt64, |
||||
Float, |
||||
Double |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an instance of a C++ built-in type.
|
||||
/// </summary>
|
||||
public class BuiltinType : Type |
||||
{ |
||||
public BuiltinType() |
||||
{ |
||||
} |
||||
|
||||
public BuiltinType(PrimitiveType type) |
||||
{ |
||||
Type = type; |
||||
} |
||||
|
||||
// Primitive type of built-in type.
|
||||
public PrimitiveType Type; |
||||
|
||||
public override string ToCSharp() |
||||
{ |
||||
return Type.ConvertToTypeName(); |
||||
} |
||||
|
||||
public override void Transform(TypeTransform transform) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
public static class PrimitiveTypeExtensions |
||||
{ |
||||
public static System.Type ConvertToType(this PrimitiveType Primitive) |
||||
{ |
||||
switch (Primitive) |
||||
{ |
||||
case PrimitiveType.Bool: return typeof(bool); |
||||
case PrimitiveType.Void: return typeof(void); |
||||
case PrimitiveType.WideChar: return typeof(char); |
||||
case PrimitiveType.Int8: return typeof(sbyte); |
||||
case PrimitiveType.UInt8: return typeof(byte); |
||||
case PrimitiveType.Int16: return typeof(short); |
||||
case PrimitiveType.UInt16: return typeof(ushort); |
||||
case PrimitiveType.Int32: return typeof(int); |
||||
case PrimitiveType.UInt32: return typeof(uint); |
||||
case PrimitiveType.Int64: return typeof(long); |
||||
case PrimitiveType.UInt64: return typeof(ulong); |
||||
case PrimitiveType.Float: return typeof(float); |
||||
case PrimitiveType.Double: return typeof(double); |
||||
} |
||||
|
||||
return typeof(int); |
||||
} |
||||
|
||||
public static string ConvertToTypeName(this PrimitiveType Primitive) |
||||
{ |
||||
switch (Primitive) |
||||
{ |
||||
case PrimitiveType.Bool: return "bool"; |
||||
case PrimitiveType.Void: return "void"; |
||||
case PrimitiveType.WideChar: return "char"; |
||||
case PrimitiveType.Int8: return "sbyte"; |
||||
case PrimitiveType.UInt8: return "byte"; |
||||
case PrimitiveType.Int16: return "short"; |
||||
case PrimitiveType.UInt16: return "ushort"; |
||||
case PrimitiveType.Int32: return "int"; |
||||
case PrimitiveType.UInt32: return "uint"; |
||||
case PrimitiveType.Int64: return "long"; |
||||
case PrimitiveType.UInt64: return "ulong"; |
||||
case PrimitiveType.Float: return "float"; |
||||
case PrimitiveType.Double: return "double"; |
||||
} |
||||
|
||||
return String.Empty; |
||||
} |
||||
} |
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Represents a C++ type reference.
|
||||
/// </summary>
|
||||
public abstract class Type |
||||
{ |
||||
public static ITypeVisitor<string> TypePrinter; |
||||
|
||||
protected Type() |
||||
{ |
||||
} |
||||
|
||||
public bool IsPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
var builtin = this as BuiltinType; |
||||
if (builtin != null) |
||||
return builtin.Type == primitive; |
||||
return false; |
||||
} |
||||
|
||||
public bool IsEnumType() |
||||
{ |
||||
var tag = this as TagType; |
||||
|
||||
if (tag == null) |
||||
return false; |
||||
|
||||
return tag.Declaration is Enumeration; |
||||
} |
||||
|
||||
public bool IsPointerToPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
var ptr = this as PointerType; |
||||
if (ptr == null) |
||||
return false; |
||||
return ptr.Pointee.IsPrimitiveType(primitive); |
||||
} |
||||
|
||||
public bool IsPointerTo<T>(out T type) where T : Type |
||||
{ |
||||
var ptr = this as PointerType; |
||||
|
||||
if (ptr == null) |
||||
{ |
||||
type = null; |
||||
return false; |
||||
} |
||||
|
||||
type = ptr.Pointee as T; |
||||
return type != null; |
||||
} |
||||
|
||||
public bool IsTagDecl<T>(out T decl) where T : Declaration |
||||
{ |
||||
var tag = this as TagType; |
||||
|
||||
if (tag == null) |
||||
{ |
||||
decl = null; |
||||
return false; |
||||
} |
||||
|
||||
decl = tag.Declaration as T; |
||||
return decl != null; |
||||
} |
||||
|
||||
public abstract T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals |
||||
= new TypeQualifiers()); |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return Visit(TypePrinter); |
||||
} |
||||
} |
||||
|
||||
public struct TypeQualifiers |
||||
{ |
||||
public bool IsConst; |
||||
public bool IsVolatile; |
||||
public bool IsRestrict; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ tag type reference.
|
||||
/// </summary>
|
||||
public class TagType : Type |
||||
{ |
||||
public TagType() |
||||
{ |
||||
} |
||||
|
||||
public Declaration Declaration; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals) |
||||
{ |
||||
return visitor.VisitTagType(this, quals); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an C/C++ array type.
|
||||
/// </summary>
|
||||
public class ArrayType : Type |
||||
{ |
||||
public enum ArraySize |
||||
{ |
||||
Constant, |
||||
Variable |
||||
} |
||||
|
||||
public ArrayType() |
||||
{ |
||||
} |
||||
|
||||
// Type of the array elements.
|
||||
public Type Type; |
||||
|
||||
// Size type of array.
|
||||
public ArraySize SizeType; |
||||
|
||||
// In case of a constant size array.
|
||||
public long Size; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals) |
||||
{ |
||||
return visitor.VisitArrayType(this, quals); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an C/C++ function type.
|
||||
/// </summary>
|
||||
public class FunctionType : Type |
||||
{ |
||||
// Return type of the function.
|
||||
public Type ReturnType; |
||||
|
||||
// Argument types.
|
||||
public List<Parameter> Arguments; |
||||
|
||||
public FunctionType() |
||||
{ |
||||
Arguments = new List<Parameter>(); |
||||
} |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals) |
||||
{ |
||||
return visitor.VisitFunctionType(this, quals); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ pointer/reference type.
|
||||
/// </summary>
|
||||
public class PointerType : Type |
||||
{ |
||||
public PointerType() |
||||
{ |
||||
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents the modifiers on a C++ type reference.
|
||||
/// </summary>
|
||||
public enum TypeModifier |
||||
{ |
||||
Value, |
||||
Pointer, |
||||
// L-value references
|
||||
LVReference, |
||||
// R-value references
|
||||
RVReference |
||||
} |
||||
|
||||
static string ConvertModifierToString(TypeModifier modifier) |
||||
{ |
||||
switch (modifier) |
||||
{ |
||||
case TypeModifier.Value: return string.Empty; |
||||
case TypeModifier.Pointer: |
||||
case TypeModifier.LVReference: |
||||
case TypeModifier.RVReference: return "*"; |
||||
} |
||||
|
||||
return string.Empty; |
||||
} |
||||
|
||||
public bool IsReference |
||||
{ |
||||
get |
||||
{ |
||||
return Modifier == TypeModifier.LVReference |
||||
|| Modifier == TypeModifier.RVReference; |
||||
} |
||||
} |
||||
|
||||
public Type Pointee; |
||||
|
||||
public TypeModifier Modifier; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals) |
||||
{ |
||||
return visitor.VisitPointerType(this, quals); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ member function pointer type.
|
||||
/// </summary>
|
||||
public class MemberPointerType : Type |
||||
{ |
||||
public MemberPointerType() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public Type Pointee; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals) |
||||
{ |
||||
return visitor.VisitMemberPointerType(this, quals); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C/C++ typedef type.
|
||||
/// </summary>
|
||||
public class TypedefType : Type |
||||
{ |
||||
public TypedefType() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public TypedefDecl Declaration; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals) |
||||
{ |
||||
return visitor.VisitTypedefType(this, quals); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a template argument within a class template specialization.
|
||||
/// </summary>
|
||||
public struct TemplateArgument |
||||
{ |
||||
/// The kind of template argument we're storing.
|
||||
public enum ArgumentKind |
||||
{ |
||||
/// The template argument is a type.
|
||||
Type, |
||||
|
||||
/// The template argument is a declaration that was provided for a
|
||||
/// pointer. reference, or pointer to member non-type template
|
||||
/// parameter.
|
||||
Declaration, |
||||
|
||||
/// The template argument is a null pointer or null pointer to member
|
||||
/// that was provided for a non-type template parameter.
|
||||
NullPtr, |
||||
|
||||
/// The template argument is an integral value that was provided for
|
||||
/// an integral non-type template parameter.
|
||||
Integral, |
||||
|
||||
/// The template argument is a template name that was provided for a
|
||||
/// template template parameter.
|
||||
Template, |
||||
|
||||
/// The template argument is a pack expansion of a template name that
|
||||
/// was provided for a template template parameter.
|
||||
TemplateExpansion, |
||||
|
||||
/// The template argument is a value- or type-dependent expression.
|
||||
Expression, |
||||
|
||||
/// The template argument is actually a parameter pack.
|
||||
Pack |
||||
} |
||||
|
||||
public ArgumentKind Kind; |
||||
public Type Type; |
||||
public Declaration Declaration; |
||||
public long Integral; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ template specialization type.
|
||||
/// </summary>
|
||||
public class TemplateSpecializationType : Type |
||||
{ |
||||
public TemplateSpecializationType() |
||||
{ |
||||
Arguments = new List<TemplateArgument>(); |
||||
} |
||||
|
||||
public List<TemplateArgument> Arguments; |
||||
|
||||
public Template Template; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, |
||||
TypeQualifiers quals = new TypeQualifiers()) |
||||
{ |
||||
return visitor.VisitTemplateSpecializationType(this, quals); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a C++ template parameter type.
|
||||
/// </summary>
|
||||
public class TemplateParameterType : Type |
||||
{ |
||||
public TemplateParameterType() |
||||
{ |
||||
} |
||||
|
||||
public TemplateParameter Parameter; |
||||
public Template Template; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, |
||||
TypeQualifiers quals = new TypeQualifiers()) |
||||
{ |
||||
//return visitor.VisitTemplateParameterType(this, quals);
|
||||
return default(T); |
||||
} |
||||
} |
||||
|
||||
#region Primitives
|
||||
|
||||
/// <summary>
|
||||
/// Represents the C++ built-in types.
|
||||
/// </summary>
|
||||
public enum PrimitiveType |
||||
{ |
||||
Null, |
||||
Void, |
||||
Bool, |
||||
WideChar, |
||||
Int8, |
||||
Char = Int8, |
||||
UInt8, |
||||
UChar = UInt8, |
||||
Int16, |
||||
UInt16, |
||||
Int32, |
||||
UInt32, |
||||
Int64, |
||||
UInt64, |
||||
Float, |
||||
Double |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an instance of a C++ built-in type.
|
||||
/// </summary>
|
||||
public class BuiltinType : Type |
||||
{ |
||||
public BuiltinType() |
||||
{ |
||||
} |
||||
|
||||
public BuiltinType(PrimitiveType type) |
||||
{ |
||||
Type = type; |
||||
} |
||||
|
||||
// Primitive type of built-in type.
|
||||
public PrimitiveType Type; |
||||
|
||||
public override T Visit<T>(ITypeVisitor<T> visitor, TypeQualifiers quals) |
||||
{ |
||||
return visitor.VisitBuiltinType(this, quals); |
||||
} |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
public interface ITypeVisitor<out T> |
||||
{ |
||||
T VisitTagType(TagType tag, TypeQualifiers quals); |
||||
T VisitArrayType(ArrayType array, TypeQualifiers quals); |
||||
T VisitFunctionType(FunctionType function, TypeQualifiers quals); |
||||
T VisitPointerType(PointerType pointer, TypeQualifiers quals); |
||||
T VisitMemberPointerType(MemberPointerType member, TypeQualifiers quals); |
||||
T VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals); |
||||
T VisitTypedefType(TypedefType typedef, TypeQualifiers quals); |
||||
T VisitTemplateSpecializationType(TemplateSpecializationType template, |
||||
TypeQualifiers quals); |
||||
T VisitDeclaration(Declaration decl, TypeQualifiers quals); |
||||
} |
||||
} |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?> |
||||
<configuration> |
||||
<startup> |
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> |
||||
</startup> |
||||
</configuration> |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
||||
<PropertyGroup> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
<ProjectGuid>{3EC927F3-5F8D-4D5D-B230-901ED2BB5D32}</ProjectGuid> |
||||
<OutputType>Library</OutputType> |
||||
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
<RootNamespace>Generator.Tests</RootNamespace> |
||||
<AssemblyName>Generator.Tests</AssemblyName> |
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
||||
<FileAlignment>512</FileAlignment> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||
<PlatformTarget>AnyCPU</PlatformTarget> |
||||
<DebugSymbols>true</DebugSymbols> |
||||
<DebugType>full</DebugType> |
||||
<Optimize>false</Optimize> |
||||
<OutputPath>bin\</OutputPath> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||
<PlatformTarget>AnyCPU</PlatformTarget> |
||||
<DebugType>pdbonly</DebugType> |
||||
<Optimize>true</Optimize> |
||||
<OutputPath>bin\</OutputPath> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
<ErrorReport>prompt</ErrorReport> |
||||
<WarningLevel>4</WarningLevel> |
||||
</PropertyGroup> |
||||
<PropertyGroup> |
||||
<StartupObject /> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<None Include="App.config" /> |
||||
<None Include="packages.config" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Compile Include="TestCLITypePrinter.cs" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Reference Include="nunit.framework"> |
||||
<HintPath>..\..\build\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath> |
||||
</Reference> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="..\Bridge\Bridge.csproj"> |
||||
<Project>{6beb8fa2-97aa-40b7-ab92-42f6eddc4490}</Project> |
||||
<Name>Bridge</Name> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\Generator\Generator.csproj"> |
||||
<Project>{73499B8E-A6A4-42FF-AB8A-754CE2780777}</Project> |
||||
<Name>Generator</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,21 @@
@@ -0,0 +1,21 @@
|
||||
using Cxxi.Generators.CLI; |
||||
using NUnit.Framework; |
||||
|
||||
namespace Generator.Tests |
||||
{ |
||||
[TestFixture] |
||||
public class CLITypePrinterTest |
||||
{ |
||||
private readonly CLITypePrinter printer; |
||||
|
||||
CLITypePrinterTest() |
||||
{ |
||||
//printer = new CLITypePrinter();
|
||||
} |
||||
|
||||
[Test] |
||||
public void Test() |
||||
{ |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<packages> |
||||
<package id="NUnit" version="2.6.2" targetFramework="net45" /> |
||||
</packages> |
||||
@ -0,0 +1,224 @@
@@ -0,0 +1,224 @@
|
||||
using System.Reflection; |
||||
using Cxxi.Generators; |
||||
using Cxxi.Passes; |
||||
using Mono.Options; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
class CodeGenerator |
||||
{ |
||||
private readonly Options options; |
||||
private Library library; |
||||
private readonly ILibrary transform; |
||||
|
||||
public CodeGenerator(Options options, ILibrary transform) |
||||
{ |
||||
this.options = options; |
||||
this.transform = transform; |
||||
} |
||||
|
||||
public void ParseCode() |
||||
{ |
||||
library = new Library(options.OutputNamespace, options.LibraryName); |
||||
|
||||
var parserOptions = new ParserOptions |
||||
{ |
||||
Library = library, |
||||
Verbose = false, |
||||
IncludeDirs = options.IncludeDirs |
||||
}; |
||||
|
||||
Console.WriteLine("Parsing code..."); |
||||
|
||||
foreach (var file in options.Headers) |
||||
{ |
||||
var path = string.Empty; |
||||
|
||||
try |
||||
{ |
||||
path = Path.GetFullPath(file); |
||||
} |
||||
catch (ArgumentException) |
||||
{ |
||||
Console.WriteLine("Invalid path '" + file + "'."); |
||||
continue; |
||||
} |
||||
|
||||
var module = new TranslationUnit(path); |
||||
parserOptions.FileName = path; |
||||
|
||||
if (!ClangParser.Parse(parserOptions)) |
||||
{ |
||||
Console.WriteLine(" Could not parse '" + file + "'."); |
||||
continue; |
||||
} |
||||
|
||||
Console.WriteLine(" Parsed '" + file + "'."); |
||||
} |
||||
} |
||||
|
||||
public void ProcessCode() |
||||
{ |
||||
if (transform != null) |
||||
transform.Preprocess(new LibraryHelpers(library)); |
||||
|
||||
var passes = new PassBuilder(); |
||||
//passes.AddPass(new Transform());
|
||||
//passes.AddPass(new Preprocess());
|
||||
|
||||
if (transform != null) |
||||
transform.SetupPasses(passes); |
||||
|
||||
var preprocess = new Preprocess(); |
||||
preprocess.ProcessLibrary(library); |
||||
|
||||
var transformer = new Transform() { Options = options, Passes = passes }; |
||||
transformer.TransformLibrary(library); |
||||
|
||||
if (transform != null) |
||||
transform.Postprocess(new LibraryHelpers(library)); |
||||
} |
||||
|
||||
public void GenerateCode() |
||||
{ |
||||
if (library.TranslationUnits.Count <= 0) |
||||
return; |
||||
|
||||
Console.WriteLine("Generating wrapper code..."); |
||||
|
||||
var gen = new Generator(options, library, transform); |
||||
gen.Generate(); |
||||
} |
||||
} |
||||
|
||||
public class Options |
||||
{ |
||||
public Options() |
||||
{ |
||||
Defines = new List<string>(); |
||||
IncludeDirs = new List<string>(); |
||||
Headers = new List<string>(); |
||||
Assembly = string.Empty; |
||||
} |
||||
|
||||
public bool Verbose = false; |
||||
public bool ShowHelpText = false; |
||||
public bool OutputDebug = false; |
||||
public string OutputNamespace; |
||||
public string OutputDir; |
||||
public string LibraryName; |
||||
public List<string> Defines; |
||||
public List<string> IncludeDirs; |
||||
public List<string> Headers; |
||||
public string Template; |
||||
public string Assembly; |
||||
} |
||||
|
||||
class Program |
||||
{ |
||||
static void ShowHelp(OptionSet options) |
||||
{ |
||||
var module = System.Diagnostics.Process.GetCurrentProcess().MainModule; |
||||
var exeName = Path.GetFileName(module.FileName); |
||||
Console.WriteLine("Usage: " + exeName + " [options]+ headers"); |
||||
Console.WriteLine("Generates .NET bindings from C/C++ header files."); |
||||
Console.WriteLine(); |
||||
Console.WriteLine("Options:"); |
||||
options.WriteOptionDescriptions(Console.Out); |
||||
} |
||||
|
||||
static bool ParseCommandLineOptions(String[] args, Options options) |
||||
{ |
||||
var set = new OptionSet() |
||||
{ |
||||
// Parser options
|
||||
{ "D|defines=", v => options.Defines.Add(v) }, |
||||
{ "I|include=", v => options.IncludeDirs.Add(v) }, |
||||
// Generator options
|
||||
{ "ns|namespace=", v => options.OutputNamespace = v }, |
||||
{ "o|outdir=", v => options.OutputDir = v }, |
||||
{ "debug", v => options.OutputDebug = true }, |
||||
{ "lib|library=", v => options.LibraryName = v }, |
||||
{ "t|template=", v => options.Template = v }, |
||||
{ "a|assembly=", v => options.Assembly = v }, |
||||
// 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) |
||||
{ |
||||
Console.WriteLine("Error parsing the command line."); |
||||
ShowHelp(set); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static bool ParseLibraryAssembly(string path, out ILibrary library) |
||||
{ |
||||
library = null; |
||||
|
||||
if (string.IsNullOrWhiteSpace(path)) |
||||
{ |
||||
Console.WriteLine("Error: no assembly provided"); |
||||
return false; |
||||
} |
||||
|
||||
try |
||||
{ |
||||
var fullPath = Path.GetFullPath(path); |
||||
|
||||
var assembly = Assembly.LoadFile(fullPath); |
||||
var types = assembly.FindDerivedTypes(typeof(ILibrary)); |
||||
|
||||
foreach (var type in types) |
||||
{ |
||||
var attrs = type.GetCustomAttributes<LibraryTransformAttribute>(); |
||||
if (attrs == null) continue; |
||||
|
||||
Console.WriteLine("Found library transform: {0}", type.Name); |
||||
library = (ILibrary)Activator.CreateInstance(type); |
||||
} |
||||
} |
||||
catch (Exception ex) |
||||
{ |
||||
Console.WriteLine("Error: assembly '{0}' could not be loaded", path); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static void Main(String[] args) |
||||
{ |
||||
var options = new Options(); |
||||
|
||||
if (!ParseCommandLineOptions(args, options)) |
||||
return; |
||||
|
||||
ILibrary library = null; |
||||
if (!ParseLibraryAssembly(options.Assembly, out library)) |
||||
return; |
||||
|
||||
var codeGenerator = new CodeGenerator(options, library); |
||||
codeGenerator.ParseCode(); |
||||
codeGenerator.ProcessCode(); |
||||
codeGenerator.GenerateCode(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,271 +0,0 @@
@@ -1,271 +0,0 @@
|
||||
using Cxxi.Templates; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
public partial class Generator |
||||
{ |
||||
public List<ModuleTransform> Transformations { get; set; } |
||||
|
||||
Library Library; |
||||
Options Options; |
||||
|
||||
public Generator(Library library, Options options) |
||||
{ |
||||
Transformations = new List<ModuleTransform>(); |
||||
|
||||
Library = library; |
||||
Options = options; |
||||
} |
||||
|
||||
public void Process() |
||||
{ |
||||
TransformModule(); |
||||
ProcessModules(); |
||||
} |
||||
|
||||
// Generates the binding code.
|
||||
public void Generate() |
||||
{ |
||||
GenerateModules(); |
||||
} |
||||
|
||||
int UniqueName = 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 ProcessDeclaration(Declaration decl) |
||||
{ |
||||
// If after all the transformations the type still does
|
||||
// not have a name, then generate one.
|
||||
|
||||
if (string.IsNullOrWhiteSpace(decl.Name)) |
||||
decl.Name = string.Format("Unnamed{0}", UniqueName++); |
||||
|
||||
CleanupText(ref decl.DebugText); |
||||
} |
||||
|
||||
void ProcessDeclarations<T>(List<T> decls) where T : Declaration |
||||
{ |
||||
foreach (T decl in decls) |
||||
ProcessDeclaration(decl); |
||||
} |
||||
|
||||
void ProcessClasses(List<Class> classes) |
||||
{ |
||||
ProcessDeclarations(classes); |
||||
|
||||
foreach (var @class in classes) |
||||
ProcessDeclarations(@class.Fields); |
||||
} |
||||
|
||||
void ProcessTypedefs(Namespace @namespace, List<Typedef> typedefs) |
||||
{ |
||||
ProcessDeclarations(typedefs); |
||||
|
||||
foreach (var typedef in typedefs) |
||||
{ |
||||
var @class = @namespace.FindClass(typedef.Name); |
||||
|
||||
// Clang will walk the typedef'd tag type and the typedef decl,
|
||||
// so we ignore the class and process just the typedef.
|
||||
|
||||
if (@class != null) |
||||
typedef.Ignore = true; |
||||
} |
||||
} |
||||
|
||||
void ProcessFunctions(List<Function> Functions) |
||||
{ |
||||
ProcessDeclarations(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)); |
||||
} |
||||
|
||||
foreach (var param in function.Parameters) |
||||
{ |
||||
ProcessDeclaration(param); |
||||
} |
||||
} |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
||||
|
||||
void ProcessNamespace(Namespace @namespace) |
||||
{ |
||||
ProcessDeclarations(@namespace.Enums); |
||||
ProcessFunctions(@namespace.Functions); |
||||
ProcessClasses(@namespace.Classes); |
||||
ProcessTypedefs(@namespace, @namespace.Typedefs); |
||||
} |
||||
|
||||
void TransformModule() |
||||
{ |
||||
if (string.IsNullOrEmpty(Library.Name)) |
||||
Library.Name = string.Empty; |
||||
|
||||
// Process everything in the global namespace for now.
|
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
foreach (Enumeration @enum in module.Enums) |
||||
TransformEnum(@enum); |
||||
|
||||
foreach (Function function in module.Functions) |
||||
TransformFunction(function); |
||||
|
||||
foreach (Class @class in module.Classes) |
||||
TransformClass(@class); |
||||
|
||||
foreach (Typedef typedef in module.Typedefs) |
||||
TransformTypedef(typedef); |
||||
} |
||||
} |
||||
|
||||
void TransformDeclaration(Declaration decl) |
||||
{ |
||||
foreach (var transform in Transformations) |
||||
transform.ProcessDeclaration(decl); |
||||
} |
||||
|
||||
void TransformTypedef(Typedef typedef) |
||||
{ |
||||
foreach (var transform in Transformations) |
||||
transform.ProcessDeclaration(typedef); |
||||
} |
||||
|
||||
void TransformClass(Class @class) |
||||
{ |
||||
TransformDeclaration(@class); |
||||
|
||||
foreach (var field in @class.Fields) |
||||
TransformDeclaration(field); |
||||
} |
||||
|
||||
void TransformFunction(Function function) |
||||
{ |
||||
TransformDeclaration(function); |
||||
|
||||
foreach (var param in function.Parameters) |
||||
TransformDeclaration(param); |
||||
} |
||||
|
||||
|
||||
void TransformEnum(Enumeration @enum) |
||||
{ |
||||
TransformDeclaration(@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,22 @@
@@ -0,0 +1,22 @@
|
||||
<?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>-ns=Flood -outdir=C:\Development\flood2\src\EngineManaged -IC:\development\flood2 -IC:\development\flood2\inc -assembly=Flood.dll Flood/Flood.cpp</StartArguments> |
||||
<StartWorkingDirectory>C:\Development\cxxi2\build\bin\</StartWorkingDirectory> |
||||
</PropertyGroup> |
||||
<PropertyGroup> |
||||
<ProjectView>ProjectFiles</ProjectView> |
||||
<PublishUrlHistory>publish\</PublishUrlHistory> |
||||
<InstallUrlHistory /> |
||||
<SupportUrlHistory /> |
||||
<UpdateUrlHistory /> |
||||
<BootstrapperUrlHistory /> |
||||
<ErrorReportUrlHistory /> |
||||
<FallbackCulture>en-US</FallbackCulture> |
||||
<VerifyUploadedFiles>false</VerifyUploadedFiles> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> |
||||
<StartWorkingDirectory>C:\Development\cxxi2\build\bin\</StartWorkingDirectory> |
||||
</PropertyGroup> |
||||
</Project> |
||||
@ -0,0 +1,327 @@
@@ -0,0 +1,327 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace Cxxi.Generators.CLI |
||||
{ |
||||
public class CLIHeadersTemplate : CLITextTemplate |
||||
{ |
||||
public override string FileExtension { get { return "h"; } } |
||||
|
||||
protected override void Generate() |
||||
{ |
||||
GenerateStart(); |
||||
|
||||
WriteLine("#pragma once"); |
||||
NewLine(); |
||||
|
||||
WriteLine("#include <{0}>", Module.IncludePath); |
||||
NewLine(); |
||||
|
||||
WriteLine("namespace {0}", SafeIdentifier(Library.Name)); |
||||
WriteLine("{"); |
||||
GenerateDeclarations(); |
||||
WriteLine("}"); |
||||
} |
||||
|
||||
public void GenerateForwardRefs() |
||||
{ |
||||
// Use a set to remove duplicate entries.
|
||||
var forwardRefs = new HashSet<string>(); |
||||
|
||||
foreach (var forwardRef in Module.ForwardReferences) |
||||
{ |
||||
var printer = new CLIForwardRefeferencePrinter(); |
||||
forwardRefs.Add(forwardRef.Visit(printer)); |
||||
} |
||||
|
||||
foreach (var forwardRef in forwardRefs) |
||||
{ |
||||
WriteLine(forwardRef); |
||||
} |
||||
|
||||
if (forwardRefs.Count > 0) |
||||
NewLine(); |
||||
} |
||||
|
||||
public void GenerateDeclarations() |
||||
{ |
||||
PushIndent(); |
||||
|
||||
// Generate the forward references.
|
||||
GenerateForwardRefs(); |
||||
|
||||
bool NeedsNewline = false; |
||||
|
||||
// Generate all the enum declarations for the module.
|
||||
for (int i = 0; i < Module.Enums.Count; ++i) |
||||
{ |
||||
var E = Module.Enums[i]; |
||||
if (E.Ignore) continue; |
||||
|
||||
GenerateEnum(E); |
||||
NeedsNewline = true; |
||||
if (i < Module.Enums.Count - 1) |
||||
NewLine(); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
NewLine(); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the typedef declarations for the module.
|
||||
for (var i = 0; i < Module.Typedefs.Count; ++i) |
||||
{ |
||||
var T = Module.Typedefs[i]; |
||||
if (T.Ignore) continue; |
||||
|
||||
GenerateTypedef(T); |
||||
NeedsNewline = true; |
||||
|
||||
if (i < Module.Typedefs.Count - 1) |
||||
NewLine(); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
NewLine(); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the struct/class declarations for the module.
|
||||
for (var i = 0; i < Module.Classes.Count; ++i) |
||||
{ |
||||
var @class = Module.Classes[i]; |
||||
|
||||
if (@class.Ignore || @class.IsIncomplete) |
||||
continue; |
||||
|
||||
if (@class.IsOpaque) |
||||
continue; |
||||
|
||||
GenerateClass(@class); |
||||
NeedsNewline = true; |
||||
|
||||
if (i < Module.Classes.Count - 1) |
||||
NewLine(); |
||||
} |
||||
|
||||
if (Module.HasFunctions) |
||||
{ |
||||
if (NeedsNewline) |
||||
NewLine(); |
||||
|
||||
WriteLine("public ref class {0}{1}", SafeIdentifier(Library.Name), |
||||
Module.FileNameWithoutExtension); |
||||
WriteLine("{"); |
||||
WriteLine("public:"); |
||||
PushIndent(); |
||||
|
||||
// Generate all the function declarations for the module.
|
||||
foreach (var function in Module.Functions) |
||||
{ |
||||
GenerateFunction(function); |
||||
} |
||||
|
||||
PopIndent(); |
||||
WriteLine("};"); |
||||
} |
||||
|
||||
PopIndent(); |
||||
} |
||||
|
||||
public void GenerateDeclarationCommon(Declaration T) |
||||
{ |
||||
GenerateSummary(T.BriefComment); |
||||
GenerateDebug(T); |
||||
} |
||||
|
||||
public void GenerateClass(Class @class) |
||||
{ |
||||
if (@class.Ignore || @class.IsIncomplete) |
||||
return; |
||||
|
||||
GenerateDeclarationCommon(@class); |
||||
|
||||
if (@class.IsUnion) |
||||
WriteLine("[StructLayout(LayoutKind.Explicit)]"); |
||||
Write("public "); |
||||
|
||||
if (@class.IsValueType) |
||||
Write("value struct "); |
||||
else |
||||
Write("ref class "); |
||||
|
||||
Write("{0}", SafeIdentifier(@class.Name)); |
||||
|
||||
if (@class.IsOpaque) |
||||
{ |
||||
WriteLine(";"); |
||||
return; |
||||
} |
||||
|
||||
if (@class.HasBase) |
||||
Write(" : {0}", SafeIdentifier(@class.Bases[0].Class.Name)); |
||||
|
||||
WriteLine(string.Empty); |
||||
WriteLine("{"); |
||||
WriteLine("public:"); |
||||
|
||||
if (!@class.IsValueType) |
||||
{ |
||||
PushIndent(); |
||||
var nativeType = string.Format("::{0}*", @class.OriginalName); |
||||
WriteLine("property {0} NativePtr;", nativeType); |
||||
PopIndent(); |
||||
NewLine(); |
||||
|
||||
// Output a default constructor that takes the native pointer.
|
||||
PushIndent(); |
||||
WriteLine("{0}({1} native);", SafeIdentifier(@class.Name), nativeType); |
||||
PopIndent(); |
||||
} |
||||
|
||||
if (@class.IsValueType) |
||||
{ |
||||
PushIndent(); |
||||
foreach(var field in @class.Fields) |
||||
{ |
||||
if (field.Ignore) continue; |
||||
|
||||
GenerateDeclarationCommon(field); |
||||
if (@class.IsUnion) |
||||
WriteLine("[FieldOffset({0})]", field.Offset); |
||||
WriteLine("{0} {1};", field.Type, SafeIdentifier(field.Name)); |
||||
} |
||||
PopIndent(); |
||||
} |
||||
|
||||
PushIndent(); |
||||
foreach (var method in @class.Methods) |
||||
{ |
||||
if (CheckIgnoreMethod(@class, method)) |
||||
continue; |
||||
|
||||
GenerateDeclarationCommon(method); |
||||
GenerateMethod(method); |
||||
} |
||||
PopIndent(); |
||||
|
||||
WriteLine("};"); |
||||
} |
||||
|
||||
public void GenerateMethod(Method method) |
||||
{ |
||||
if (method.Ignore) return; |
||||
|
||||
if (method.Access != AccessSpecifier.Public) |
||||
return; |
||||
|
||||
GenerateDeclarationCommon(method); |
||||
|
||||
if (method.Kind == CXXMethodKind.Constructor || method.Kind == CXXMethodKind.Destructor) |
||||
Write("{0}(", SafeIdentifier(method.Name)); |
||||
else |
||||
Write("{0} {1}(", method.ReturnType, SafeIdentifier(method.Name)); |
||||
|
||||
for (int i = 0; i < method.Parameters.Count; ++i) |
||||
{ |
||||
var param = method.Parameters[i]; |
||||
Write("{0}", TypeSig.GetArgumentString(param)); |
||||
if (i < method.Parameters.Count - 1) |
||||
Write(", "); |
||||
} |
||||
|
||||
WriteLine(");"); |
||||
} |
||||
|
||||
public void GenerateTypedef(TypedefDecl typedef) |
||||
{ |
||||
if (typedef.Ignore) return; |
||||
GenerateDeclarationCommon(typedef); |
||||
|
||||
FunctionType func; |
||||
TagType tag; |
||||
|
||||
//if (T.Type.IsPointerToPrimitiveType(PrimitiveType.Void)
|
||||
// || T.Type.IsPointerTo<TagType>(out tag))
|
||||
//{
|
||||
// WriteLine("public class " + SafeIdentifier(T.Name) + @" { }");
|
||||
// NewLine();
|
||||
//}
|
||||
//else
|
||||
if (typedef.Type.IsPointerTo<FunctionType>(out func)) |
||||
{ |
||||
WriteLine("public {0};", |
||||
string.Format(TypeSig.ToDelegateString(func), |
||||
SafeIdentifier(typedef.Name))); |
||||
} |
||||
else if (typedef.Type.IsEnumType()) |
||||
{ |
||||
// Already handled in the parser.
|
||||
} |
||||
else |
||||
{ |
||||
Console.WriteLine("Unhandled typedef type: {0}", typedef); |
||||
} |
||||
} |
||||
|
||||
public void GenerateFunction(Function function) |
||||
{ |
||||
if (function.Ignore) return; |
||||
GenerateDeclarationCommon(function); |
||||
|
||||
Write("static {0} {1}(", function.ReturnType, SafeIdentifier(function.Name)); |
||||
|
||||
for (int i = 0; i < function.Parameters.Count; ++i) |
||||
{ |
||||
var param = function.Parameters[i]; |
||||
Write("{0}", TypeSig.GetArgumentString(param)); |
||||
if (i < function.Parameters.Count - 1) |
||||
Write(", "); |
||||
} |
||||
|
||||
WriteLine(");"); |
||||
} |
||||
|
||||
public void GenerateDebug(Declaration decl) |
||||
{ |
||||
if (Options.OutputDebug && !String.IsNullOrWhiteSpace(decl.DebugText)) |
||||
WriteLine("// DEBUG: " + decl.DebugText); |
||||
} |
||||
|
||||
public void GenerateEnum(Enumeration @enum) |
||||
{ |
||||
if (@enum.Ignore) return; |
||||
GenerateDeclarationCommon(@enum); |
||||
|
||||
if (@enum.Modifiers.HasFlag(Enumeration.EnumModifiers.Flags)) |
||||
WriteLine("[System::Flags]"); |
||||
|
||||
Write("public enum struct {0}", SafeIdentifier(@enum.Name)); |
||||
|
||||
if (@enum.BuiltinType.Type != PrimitiveType.Int32) |
||||
WriteLine(" : {0}", TypeSig.VisitPrimitiveType(@enum.BuiltinType.Type)); |
||||
else |
||||
NewLine(); |
||||
|
||||
WriteLine("{"); |
||||
|
||||
PushIndent(); |
||||
for (int i = 0; i < @enum.Items.Count; ++i) |
||||
{ |
||||
var I = @enum.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 < @enum.Items.Count - 1) |
||||
WriteLine(","); |
||||
} |
||||
PopIndent(); |
||||
NewLine(); |
||||
WriteLine("};"); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,449 @@
@@ -0,0 +1,449 @@
|
||||
using System; |
||||
using System.IO; |
||||
using Cxxi.Types; |
||||
|
||||
namespace Cxxi.Generators.CLI |
||||
{ |
||||
#region CLI Type Visitors
|
||||
public class CLITypePrinter : ITypeVisitor<string>, IDeclVisitor<string> |
||||
{ |
||||
public Generator Generator { get; set; } |
||||
public Library Library { get; set; } |
||||
|
||||
public CLITypePrinter(Generator generator) |
||||
{ |
||||
Generator = generator; |
||||
Library = generator.Library; |
||||
} |
||||
|
||||
public string VisitTagType(TagType tag, TypeQualifiers quals) |
||||
{ |
||||
Declaration decl = tag.Declaration; |
||||
|
||||
if (decl == null) |
||||
return string.Empty; |
||||
|
||||
return VisitDeclaration(decl, quals); |
||||
} |
||||
|
||||
public string VisitArrayType(ArrayType array, TypeQualifiers quals) |
||||
{ |
||||
return string.Format("array<{0}>", array.Type.Visit(this)); |
||||
} |
||||
|
||||
public string VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||
{ |
||||
var arguments = function.Arguments; |
||||
var returnType = function.ReturnType; |
||||
|
||||
string args = string.Empty; |
||||
|
||||
if (arguments.Count > 0) |
||||
args = GetArgumentsString(function, hasNames: false); |
||||
|
||||
if (returnType.IsPrimitiveType(PrimitiveType.Void)) |
||||
{ |
||||
if (!string.IsNullOrEmpty(args)) |
||||
args = string.Format("<{0}>", args); |
||||
return string.Format("System::Action{0}", args); |
||||
} |
||||
|
||||
if (!string.IsNullOrEmpty(args)) |
||||
args = string.Format(", {0}", args); |
||||
|
||||
return string.Format("System::Func<{0}{1}>", returnType.Visit(this), args); |
||||
} |
||||
|
||||
public string GetArgumentsString(FunctionType function, bool hasNames) |
||||
{ |
||||
var arguments = function.Arguments; |
||||
var s = string.Empty; |
||||
|
||||
for (var i = 0; i < arguments.Count; ++i) |
||||
{ |
||||
s += GetArgumentString(arguments[i], hasNames); |
||||
if (i < arguments.Count - 1) |
||||
s += ", "; |
||||
} |
||||
|
||||
return s; |
||||
} |
||||
|
||||
public string GetArgumentString(Parameter arg, bool hasName = true) |
||||
{ |
||||
var quals = new TypeQualifiers {IsConst = arg.IsConst}; |
||||
|
||||
var type = arg.Type.Visit(this, quals); |
||||
var name = arg.Name; |
||||
|
||||
if (hasName && !string.IsNullOrEmpty(name)) |
||||
return string.Format("{0} {1}", type, name); |
||||
|
||||
return type; |
||||
} |
||||
|
||||
public string ToDelegateString(FunctionType function) |
||||
{ |
||||
return string.Format("delegate {0} {{0}}({1})", |
||||
function.ReturnType.Visit(this), |
||||
GetArgumentsString(function, hasNames: true)); |
||||
} |
||||
|
||||
public string VisitPointerType(PointerType pointer, TypeQualifiers quals) |
||||
{ |
||||
var pointee = pointer.Pointee; |
||||
|
||||
if (pointee is FunctionType) |
||||
{ |
||||
var function = pointee as FunctionType; |
||||
return string.Format("{0}^", function.Visit(this, quals)); |
||||
} |
||||
|
||||
if (pointee.IsPrimitiveType(PrimitiveType.Void)) |
||||
return "System::IntPtr"; |
||||
|
||||
if (pointee.IsPrimitiveType(PrimitiveType.Char)) |
||||
return "System::String^"; |
||||
|
||||
return pointee.Visit(this, quals); |
||||
} |
||||
|
||||
public string VisitMemberPointerType(MemberPointerType member, |
||||
TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
return VisitPrimitiveType(builtin.Type); |
||||
} |
||||
|
||||
public string VisitPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
switch (primitive) |
||||
{ |
||||
case PrimitiveType.Bool: return "bool"; |
||||
case PrimitiveType.Void: return "void"; |
||||
case PrimitiveType.WideChar: return "char"; |
||||
case PrimitiveType.Int8: return "char"; |
||||
case PrimitiveType.UInt8: return "unsigned char"; |
||||
case PrimitiveType.Int16: return "short"; |
||||
case PrimitiveType.UInt16: return "unsigned short"; |
||||
case PrimitiveType.Int32: return "int"; |
||||
case PrimitiveType.UInt32: return "unsigned int"; |
||||
case PrimitiveType.Int64: return "long"; |
||||
case PrimitiveType.UInt64: return "unsigned long"; |
||||
case PrimitiveType.Float: return "float"; |
||||
case PrimitiveType.Double: return "double"; |
||||
} |
||||
|
||||
return string.Empty; |
||||
} |
||||
|
||||
public string VisitTypedefType(TypedefType typedef, TypeQualifiers quals) |
||||
{ |
||||
var decl = typedef.Declaration; |
||||
|
||||
if (string.IsNullOrEmpty(decl.Name)) |
||||
return null; |
||||
|
||||
TypeMap typeMap = null; |
||||
if (Generator.TypeDatabase.FindTypeMap(decl.QualifiedOriginalName, out typeMap)) |
||||
{ |
||||
return typeMap.Signature(); |
||||
} |
||||
|
||||
FunctionType func; |
||||
if (typedef.Declaration.Type.IsPointerTo<FunctionType>(out func)) |
||||
{ |
||||
// TODO: Use SafeIdentifier()
|
||||
return string.Format("{0}^", typedef.Declaration.Name); |
||||
} |
||||
|
||||
return decl.Type.Visit(this); |
||||
} |
||||
|
||||
public string VisitTemplateSpecializationType(TemplateSpecializationType template, |
||||
TypeQualifiers quals) |
||||
{ |
||||
var decl = template.Template.TemplatedDecl; |
||||
|
||||
TypeMap typeMap = null; |
||||
if (Generator.TypeDatabase.FindTypeMap(decl.QualifiedOriginalName, out typeMap)) |
||||
{ |
||||
typeMap.Declaration = decl; |
||||
typeMap.Type = template; |
||||
return typeMap.Signature(); |
||||
} |
||||
|
||||
return decl.Name; |
||||
} |
||||
|
||||
public string VisitDeclaration(Declaration decl, TypeQualifiers quals) |
||||
{ |
||||
return VisitDeclaration(decl); |
||||
} |
||||
|
||||
public string VisitDeclaration(Declaration decl) |
||||
{ |
||||
var name = decl.Visit(this); |
||||
return string.Format("{0}::{1}", Library.Name, name); |
||||
} |
||||
|
||||
public string VisitClassDecl(Class @class) |
||||
{ |
||||
return string.Format("{0}{1}", @class.Name, @class.IsRefType ? "^" |
||||
: string.Empty); |
||||
} |
||||
|
||||
public string VisitFieldDecl(Field field) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitFunctionDecl(Function function) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitMethodDecl(Method method) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitParameterDecl(Parameter parameter) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitTypedefDecl(TypedefDecl typedef) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
return @enum.Name; |
||||
} |
||||
|
||||
public string VisitClassTemplateDecl(ClassTemplate template) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitFunctionTemplateDecl(FunctionTemplate template) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitMacroDefinition(MacroDefinition macro) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public class CLIForwardRefeferencePrinter : IDeclVisitor<string> |
||||
{ |
||||
public string VisitDeclaration(Declaration decl) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitClassDecl(Class @class) |
||||
{ |
||||
if (@class.IsValueType) |
||||
return string.Format("value struct {0};", @class.Name); |
||||
return string.Format("ref class {0};", @class.Name); |
||||
} |
||||
|
||||
public string VisitFieldDecl(Field field) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitFunctionDecl(Function function) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitMethodDecl(Method method) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitParameterDecl(Parameter parameter) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitTypedefDecl(TypedefDecl typedef) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
if (@enum.Type.IsPrimitiveType(PrimitiveType.Int32)) |
||||
return string.Format("enum struct {0};", @enum.Name); |
||||
return string.Format("enum struct {0} : {1};", @enum.Name, |
||||
@enum.Type); |
||||
} |
||||
|
||||
public string VisitClassTemplateDecl(ClassTemplate template) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitFunctionTemplateDecl(FunctionTemplate template) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitMacroDefinition(MacroDefinition macro) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region CLI Text Templates
|
||||
public abstract class CLITextTemplate : TextTemplate |
||||
{ |
||||
protected const string DefaultIndent = " "; |
||||
protected const uint MaxIndent = 80; |
||||
|
||||
public CLITypePrinter TypeSig { get; set; } |
||||
|
||||
public static string SafeIdentifier(string proposedName) |
||||
{ |
||||
return proposedName; |
||||
} |
||||
|
||||
public string QualifiedIdentifier(Declaration decl) |
||||
{ |
||||
return string.Format("{0}::{1}", Library.Name, decl.Name); |
||||
} |
||||
|
||||
public void GenerateStart() |
||||
{ |
||||
Transform.GenerateStart(this); |
||||
} |
||||
|
||||
public void GenerateAfterNamespaces() |
||||
{ |
||||
Transform.GenerateAfterNamespaces(this); |
||||
} |
||||
|
||||
public void GenerateSummary(string comment) |
||||
{ |
||||
if (String.IsNullOrWhiteSpace(comment)) |
||||
return; |
||||
|
||||
// Wrap the comment to the line width.
|
||||
var maxSize = (int)(MaxIndent - CurrentIndent.Count - "/// ".Length); |
||||
var lines = StringHelpers.WordWrapLines(comment, maxSize); |
||||
|
||||
WriteLine("/// <summary>"); |
||||
foreach (string line in lines) |
||||
WriteLine(string.Format("/// {0}", line.TrimEnd())); |
||||
WriteLine("/// </summary>"); |
||||
} |
||||
|
||||
public void GenerateInlineSummary(string comment) |
||||
{ |
||||
if (String.IsNullOrWhiteSpace(comment)) |
||||
return; |
||||
WriteLine("/// <summary> {0} </summary>", comment); |
||||
} |
||||
|
||||
public static bool CheckIgnoreMethod(Class @class, Method method) |
||||
{ |
||||
if (method.Ignore) return true; |
||||
|
||||
if (@class.IsAbstract && method.IsConstructor) |
||||
return true; |
||||
|
||||
if (@class.IsValueType && method.IsDefaultConstructor) |
||||
return true; |
||||
|
||||
if (method.IsCopyConstructor || method.IsMoveConstructor) |
||||
return true; |
||||
|
||||
if (method.IsDestructor) |
||||
return true; |
||||
|
||||
if (method.OperatorKind == CXXOperatorKind.Equal) |
||||
return true; |
||||
|
||||
if (method.Kind == CXXMethodKind.Conversion) |
||||
return true; |
||||
|
||||
if (method.Access != AccessSpecifier.Public) |
||||
return true; |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public abstract override string FileExtension { get; } |
||||
|
||||
protected abstract override void Generate(); |
||||
} |
||||
#endregion
|
||||
|
||||
public class CLIGenerator : ILanguageGenerator |
||||
{ |
||||
public Options Options { get; set; } |
||||
public Library Library { get; set; } |
||||
public ILibrary Transform { get; set; } |
||||
public Generator Generator { get; set; } |
||||
|
||||
private readonly CLITypePrinter typePrinter; |
||||
|
||||
public CLIGenerator(Generator generator) |
||||
{ |
||||
Generator = generator; |
||||
typePrinter = new CLITypePrinter(generator); |
||||
Type.TypePrinter = typePrinter; |
||||
} |
||||
|
||||
T CreateTemplate<T>(TranslationUnit unit) where T : CLITextTemplate, new() |
||||
{ |
||||
var template = new T |
||||
{ |
||||
Generator = Generator, |
||||
Options = Options, |
||||
Library = Library, |
||||
Transform = Transform, |
||||
Module = unit, |
||||
TypeSig = typePrinter |
||||
}; |
||||
|
||||
return template; |
||||
} |
||||
|
||||
void WriteTemplate(TextTemplate template) |
||||
{ |
||||
var file = Path.GetFileNameWithoutExtension(template.Module.FileName) + "." |
||||
+ template.FileExtension; |
||||
|
||||
var path = Path.Combine(Options.OutputDir, file); |
||||
|
||||
Console.WriteLine(" Generated '" + file + "'."); |
||||
File.WriteAllText(Path.GetFullPath(path), template.ToString()); |
||||
} |
||||
|
||||
public bool Generate(TranslationUnit unit) |
||||
{ |
||||
typePrinter.Library = Library; |
||||
|
||||
var header = CreateTemplate<CLIHeadersTemplate>(unit); |
||||
WriteTemplate(header); |
||||
|
||||
var source = CreateTemplate<CLISourcesTemplate>(unit); |
||||
WriteTemplate(source); |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,412 @@
@@ -0,0 +1,412 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Text; |
||||
using Cxxi.Types; |
||||
|
||||
namespace Cxxi.Generators.CLI |
||||
{ |
||||
public class CLIMarshalNativeToManagedPrinter : ITypeVisitor<bool>, |
||||
IDeclVisitor<bool> |
||||
{ |
||||
public string Support = null; |
||||
public string Return = null; |
||||
|
||||
Generator Generator { get; set; } |
||||
MarshalContext Context { get; set; } |
||||
|
||||
public CLIMarshalNativeToManagedPrinter(Generator gen, MarshalContext ctx) |
||||
{ |
||||
Generator = gen; |
||||
Context = ctx; |
||||
} |
||||
|
||||
public bool VisitTagType(TagType tag, TypeQualifiers quals) |
||||
{ |
||||
var decl = tag.Declaration; |
||||
return decl.Visit(this); |
||||
} |
||||
|
||||
public bool VisitArrayType(ArrayType array, TypeQualifiers quals) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public bool VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||
{ |
||||
var returnType = function.ReturnType; |
||||
return returnType.Visit(this, quals); |
||||
} |
||||
|
||||
public bool VisitPointerType(PointerType pointer, TypeQualifiers quals) |
||||
{ |
||||
var pointee = pointer.Pointee; |
||||
|
||||
if (pointee.IsPrimitiveType(PrimitiveType.Void)) |
||||
{ |
||||
Return = "IntPtr()"; |
||||
return true; |
||||
} |
||||
|
||||
if (pointee.IsPrimitiveType(PrimitiveType.Char)) |
||||
{ |
||||
Return = string.Format("clix::marshalString<clix::E_UTF8>({0})", |
||||
Context.ReturnVarName); |
||||
return true; |
||||
} |
||||
|
||||
if (!pointee.Visit(this, quals)) |
||||
return false; |
||||
|
||||
if (pointer.IsReference) |
||||
Return = string.Format("&{0}", Return); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public bool VisitMemberPointerType(MemberPointerType member, |
||||
TypeQualifiers quals) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
return VisitPrimitiveType(builtin.Type); |
||||
} |
||||
|
||||
public bool VisitPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
switch (primitive) |
||||
{ |
||||
case PrimitiveType.Void: |
||||
return true; |
||||
case PrimitiveType.Bool: |
||||
case PrimitiveType.Int8: |
||||
case PrimitiveType.UInt8: |
||||
case PrimitiveType.Int16: |
||||
case PrimitiveType.UInt16: |
||||
case PrimitiveType.Int32: |
||||
case PrimitiveType.UInt32: |
||||
case PrimitiveType.Int64: |
||||
case PrimitiveType.UInt64: |
||||
case PrimitiveType.Float: |
||||
case PrimitiveType.Double: |
||||
Return = Context.ReturnVarName; |
||||
return true; |
||||
case PrimitiveType.WideChar: |
||||
return false; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) |
||||
{ |
||||
var decl = typedef.Declaration; |
||||
|
||||
TypeMap typeMap = null; |
||||
var typeDb = Generator.TypeDatabase; |
||||
if (typeDb.FindTypeMap(decl.QualifiedOriginalName, out typeMap)) |
||||
{ |
||||
Return = typeMap.MarshalFromNative(Context); |
||||
return typeMap.IsValueType; |
||||
} |
||||
|
||||
// TODO: How should function pointers behave here?
|
||||
|
||||
return decl.Type.Visit(this); |
||||
} |
||||
|
||||
public bool VisitTemplateSpecializationType(TemplateSpecializationType template, |
||||
TypeQualifiers quals) |
||||
{ |
||||
return template.Template.Visit(this); |
||||
} |
||||
|
||||
public bool VisitDeclaration(Declaration decl, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitClassDecl(Class @class) |
||||
{ |
||||
Return = string.Format("gcnew {0}({1})", @class.Name, Context.ReturnVarName); |
||||
return @class.IsValueType; |
||||
} |
||||
|
||||
public bool VisitFieldDecl(Field field) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitFunctionDecl(Function function) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitMethodDecl(Method method) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitParameterDecl(Parameter parameter) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitTypedefDecl(TypedefDecl typedef) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
Return = string.Format("({0}){1}", ToCLITypeName(@enum), Context.ReturnVarName); |
||||
return true; |
||||
} |
||||
|
||||
private string ToCLITypeName(Declaration decl) |
||||
{ |
||||
var typePrinter = new CLITypePrinter(Generator); |
||||
return typePrinter.VisitDeclaration(decl); |
||||
} |
||||
|
||||
public bool VisitClassTemplateDecl(ClassTemplate template) |
||||
{ |
||||
return template.TemplatedClass.Visit(this); |
||||
} |
||||
|
||||
public bool VisitFunctionTemplateDecl(FunctionTemplate template) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitMacroDefinition(MacroDefinition macro) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public class CLIMarshalManagedToNativePrinter : ITypeVisitor<bool>, |
||||
IDeclVisitor<bool> |
||||
{ |
||||
public string Support = null; |
||||
public string Return = null; |
||||
|
||||
Generator Generator { get; set; } |
||||
MarshalContext Context { get; set; } |
||||
|
||||
public CLIMarshalManagedToNativePrinter(Generator gen, MarshalContext ctx) |
||||
{ |
||||
Generator = gen; |
||||
Context = ctx; |
||||
} |
||||
|
||||
public bool VisitTagType(TagType tag, TypeQualifiers quals) |
||||
{ |
||||
var decl = tag.Declaration; |
||||
return decl.Visit(this); |
||||
} |
||||
|
||||
public bool VisitArrayType(ArrayType array, TypeQualifiers quals) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public bool VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||
{ |
||||
var returnType = function.ReturnType; |
||||
return returnType.Visit(this, quals); |
||||
} |
||||
|
||||
public bool VisitDelegateType(FunctionType function, string type) |
||||
{ |
||||
// We marshal function pointer types by calling
|
||||
// GetFunctionPointerForDelegate to get a native function
|
||||
// pointer ouf of the delegate. Then we can pass it in the
|
||||
// native call. Since references are not tracked in the
|
||||
// native side, we need to be careful and protect it with an
|
||||
// explicit GCHandle if necessary.
|
||||
|
||||
var sb = new StringBuilder(); |
||||
sb.AppendFormat("static_cast<::{0}>(", type); |
||||
sb.Append("System::Runtime::InteropServices::Marshal::"); |
||||
sb.Append("GetFunctionPointerForDelegate("); |
||||
sb.AppendFormat("{0}).ToPointer())", Context.Parameter.Name); |
||||
Return = sb.ToString(); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public bool VisitPointerType(PointerType pointer, TypeQualifiers quals) |
||||
{ |
||||
var pointee = pointer.Pointee; |
||||
|
||||
if (pointee.IsPrimitiveType(PrimitiveType.Void)) |
||||
{ |
||||
Return = string.Format("{0}.ToPointer()", Context.Parameter.Name); |
||||
return true; |
||||
} |
||||
|
||||
if (pointee.IsPrimitiveType(PrimitiveType.Char)) |
||||
{ |
||||
Support = string.Format( |
||||
"auto _{0} = clix::marshalString<clix::E_UTF8>({1});", |
||||
Context.ArgName, Context.Parameter.Name); |
||||
|
||||
Return = string.Format("_{0}.c_str()", Context.ArgName); |
||||
return true; |
||||
} |
||||
|
||||
if (pointee is FunctionType) |
||||
{ |
||||
var function = pointee as FunctionType; |
||||
// TODO: We have to translate the function type typedef to C/C++
|
||||
return VisitDelegateType(function, function.ToString()); |
||||
} |
||||
|
||||
return pointee.Visit(this, quals); |
||||
} |
||||
|
||||
public bool VisitMemberPointerType(MemberPointerType member, |
||||
TypeQualifiers quals) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
return VisitPrimitiveType(builtin.Type); |
||||
} |
||||
|
||||
public bool VisitPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
switch (primitive) |
||||
{ |
||||
case PrimitiveType.Void: |
||||
return true; |
||||
case PrimitiveType.Bool: |
||||
case PrimitiveType.Int8: |
||||
case PrimitiveType.UInt8: |
||||
case PrimitiveType.Int16: |
||||
case PrimitiveType.UInt16: |
||||
case PrimitiveType.Int32: |
||||
case PrimitiveType.UInt32: |
||||
case PrimitiveType.Int64: |
||||
case PrimitiveType.UInt64: |
||||
case PrimitiveType.Float: |
||||
case PrimitiveType.Double: |
||||
Return = Context.Parameter.Name; |
||||
return true; |
||||
case PrimitiveType.WideChar: |
||||
return false; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) |
||||
{ |
||||
var decl = typedef.Declaration; |
||||
|
||||
TypeMap typeMap = null; |
||||
if (Generator.TypeDatabase.FindTypeMap(decl.QualifiedOriginalName, out typeMap)) |
||||
{ |
||||
Return = typeMap.MarshalToNative(Context); |
||||
return typeMap.IsValueType; |
||||
} |
||||
|
||||
FunctionType func; |
||||
if (typedef.Declaration.Type.IsPointerTo<FunctionType>(out func)) |
||||
{ |
||||
VisitDelegateType(func, typedef.Declaration.OriginalName); |
||||
return true; |
||||
} |
||||
|
||||
return decl.Type.Visit(this); |
||||
} |
||||
|
||||
public bool VisitTemplateSpecializationType(TemplateSpecializationType template, |
||||
TypeQualifiers quals) |
||||
{ |
||||
return template.Template.Visit(this); |
||||
} |
||||
|
||||
public bool VisitDeclaration(Declaration decl, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitClassDecl(Class @class) |
||||
{ |
||||
if (@class.IsValueType) |
||||
{ |
||||
Return = string.Format("(::{0}*)&{1}", @class.OriginalName, |
||||
Context.Parameter.Name); |
||||
} |
||||
else |
||||
{ |
||||
Return = string.Format("{0}->NativePtr", Context.Parameter.Name); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public bool VisitFieldDecl(Field field) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitFunctionDecl(Function function) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitMethodDecl(Method method) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitParameterDecl(Parameter parameter) |
||||
{ |
||||
return parameter.Type.Visit(this); |
||||
} |
||||
|
||||
public bool VisitTypedefDecl(TypedefDecl typedef) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
Return = string.Format("(::{0}){1}", @enum.QualifiedOriginalName, |
||||
Context.Parameter.Name); |
||||
return true; |
||||
} |
||||
|
||||
public bool VisitClassTemplateDecl(ClassTemplate template) |
||||
{ |
||||
return template.TemplatedClass.Visit(this); |
||||
} |
||||
|
||||
public bool VisitFunctionTemplateDecl(FunctionTemplate template) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitMacroDefinition(MacroDefinition macro) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,285 @@
@@ -0,0 +1,285 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Globalization; |
||||
using System.IO; |
||||
using Cxxi.Types; |
||||
|
||||
namespace Cxxi.Generators.CLI |
||||
{ |
||||
public class CLISourcesTemplate : CLITextTemplate |
||||
{ |
||||
protected override void Generate() |
||||
{ |
||||
GenerateStart(); |
||||
|
||||
WriteLine("#include \"{0}.h\"", |
||||
Path.GetFileNameWithoutExtension(Module.FileName)); |
||||
NewLine(); |
||||
|
||||
GenerateForwardReferenceHeaders(); |
||||
NewLine(); |
||||
|
||||
WriteLine("using namespace System;"); |
||||
WriteLine("using namespace System::Runtime::InteropServices;"); |
||||
GenerateAfterNamespaces(); |
||||
NewLine(); |
||||
|
||||
GenerateDeclarations(); |
||||
} |
||||
|
||||
public void GenerateForwardReferenceHeaders() |
||||
{ |
||||
var includes = new HashSet<string>(); |
||||
|
||||
// Generate the forward references.
|
||||
foreach (var decl in Module.ForwardReferences) |
||||
{ |
||||
var @namespace = decl.Namespace; |
||||
var unit = @namespace.TranslationUnit; |
||||
|
||||
if (unit.Ignore) |
||||
continue; |
||||
|
||||
if (unit.IsSystemHeader) |
||||
continue; |
||||
|
||||
var includeName = Path.GetFileNameWithoutExtension(unit.FileName); |
||||
|
||||
if (includeName == Path.GetFileNameWithoutExtension(Module.FileName)) |
||||
continue; |
||||
|
||||
includes.Add(includeName); |
||||
} |
||||
|
||||
foreach (var include in includes) |
||||
{ |
||||
WriteLine("#include \"{0}.h\"", include); |
||||
} |
||||
} |
||||
|
||||
public void GenerateDeclarations() |
||||
{ |
||||
// Generate all the struct/class definitions for the module.
|
||||
for (var i = 0; i < Module.Classes.Count; ++i) |
||||
{ |
||||
var @class = Module.Classes[i]; |
||||
|
||||
if (@class.Ignore) |
||||
continue; |
||||
|
||||
if (@class.IsOpaque || @class.IsIncomplete) |
||||
continue; |
||||
|
||||
GenerateClass(@class); |
||||
} |
||||
|
||||
if (Module.HasFunctions) |
||||
{ |
||||
var staticClassName = Library.Name + Module.FileNameWithoutExtension; |
||||
|
||||
// Generate all the function declarations for the module.
|
||||
for (var i = 0; i < Module.Functions.Count; ++i) |
||||
{ |
||||
var function = Module.Functions[i]; |
||||
|
||||
if (function.Ignore) |
||||
continue; |
||||
|
||||
GenerateFunction(function, staticClassName); |
||||
NewLine(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void GenerateDeclarationCommon(Declaration decl) |
||||
{ |
||||
} |
||||
|
||||
public void GenerateClass(Class @class) |
||||
{ |
||||
GenerateDeclarationCommon(@class); |
||||
|
||||
if (!@class.IsValueType) |
||||
{ |
||||
// Output a default constructor that takes the native pointer.
|
||||
Write("{0}::{1}(", QualifiedIdentifier(@class), SafeIdentifier(@class.Name)); |
||||
var nativeType = string.Format("::{0}*", @class.OriginalName); |
||||
WriteLine("{0} native)", nativeType); |
||||
WriteLine("{"); |
||||
|
||||
PushIndent(); |
||||
WriteLine("NativePtr = native;"); |
||||
PopIndent(); |
||||
|
||||
WriteLine("}"); |
||||
|
||||
NewLine(); |
||||
} |
||||
|
||||
foreach (var method in @class.Methods) |
||||
{ |
||||
if (CheckIgnoreMethod(@class, method)) |
||||
continue; |
||||
|
||||
GenerateDeclarationCommon(method); |
||||
GenerateMethod(method, @class); |
||||
|
||||
NewLine(); |
||||
} |
||||
} |
||||
|
||||
public void GenerateMethod(Method method, Class @class) |
||||
{ |
||||
GenerateDeclarationCommon(method); |
||||
|
||||
if (method.Kind == CXXMethodKind.Constructor || method.Kind == CXXMethodKind.Destructor) |
||||
Write("{0}::{1}(", QualifiedIdentifier(@class), SafeIdentifier(method.Name)); |
||||
else |
||||
Write("{0} {1}::{2}(", method.ReturnType, QualifiedIdentifier(@class), |
||||
SafeIdentifier(method.Name)); |
||||
|
||||
for (var i = 0; i < method.Parameters.Count; ++i) |
||||
{ |
||||
var param = method.Parameters[i]; |
||||
Write("{0}", TypeSig.GetArgumentString(param)); |
||||
if (i < method.Parameters.Count - 1) |
||||
Write(", "); |
||||
} |
||||
|
||||
WriteLine(")"); |
||||
WriteLine("{"); |
||||
PushIndent(); |
||||
|
||||
if (@class.IsRefType) |
||||
{ |
||||
if (method.Kind == CXXMethodKind.Constructor) |
||||
{ |
||||
var @params = GenerateFunctionParamsMarshal(method); |
||||
Write("NativePtr = new ::{0}(", method.QualifiedOriginalName); |
||||
GenerateFunctionParams(method, @params); |
||||
WriteLine(");"); |
||||
} |
||||
else |
||||
{ |
||||
GenerateFunctionCall(method); |
||||
} |
||||
} |
||||
|
||||
PopIndent(); |
||||
WriteLine("}"); |
||||
} |
||||
|
||||
public void GenerateFunction(Function function, string className) |
||||
{ |
||||
if (function.Ignore) |
||||
return; |
||||
|
||||
GenerateDeclarationCommon(function); |
||||
|
||||
Write("{0} {1}::{2}::{3}(", function.ReturnType, Library.Name, className, |
||||
SafeIdentifier(function.Name)); |
||||
|
||||
for (var i = 0; i < function.Parameters.Count; ++i) |
||||
{ |
||||
var param = function.Parameters[i]; |
||||
Write("{0}", TypeSig.GetArgumentString(param)); |
||||
if (i < function.Parameters.Count - 1) |
||||
Write(", "); |
||||
} |
||||
|
||||
WriteLine(")"); |
||||
WriteLine("{"); |
||||
PushIndent(); |
||||
|
||||
GenerateFunctionCall(function); |
||||
|
||||
PopIndent(); |
||||
WriteLine("}"); |
||||
} |
||||
|
||||
public void GenerateFunctionCall(Function function) |
||||
{ |
||||
var retType = function.ReturnType; |
||||
var needsReturn = !retType.IsPrimitiveType(PrimitiveType.Void); |
||||
|
||||
var @params = GenerateFunctionParamsMarshal(function); |
||||
|
||||
if (needsReturn) |
||||
Write("auto ret = "); |
||||
|
||||
if (function is Method) |
||||
Write("NativePtr->"); |
||||
else |
||||
Write("::"); |
||||
|
||||
Write("{0}(", function.QualifiedOriginalName); |
||||
GenerateFunctionParams(function, @params); |
||||
WriteLine(");"); |
||||
|
||||
if (needsReturn) |
||||
{ |
||||
Write("return "); |
||||
|
||||
var ctx = new MarshalContext() { ReturnVarName = "ret" }; |
||||
var marshal = new CLIMarshalNativeToManagedPrinter(Generator, ctx); |
||||
function.ReturnType.Visit(marshal); |
||||
|
||||
WriteLine("{0};", marshal.Return); |
||||
} |
||||
} |
||||
|
||||
public List<string> GenerateFunctionParamsMarshal(Function function) |
||||
{ |
||||
var @params = new List<string>(); |
||||
|
||||
// Do marshalling of parameters
|
||||
for (var i = 0; i < function.Parameters.Count; ++i) |
||||
{ |
||||
var param = function.Parameters[i]; |
||||
|
||||
if (param.Type is BuiltinType) |
||||
{ |
||||
@params.Add(param.Name); |
||||
} |
||||
else |
||||
{ |
||||
var argName = "arg" + i.ToString(CultureInfo.InvariantCulture); |
||||
var ctx = new MarshalContext() { Parameter = param, ArgName = argName }; |
||||
var marshal = new CLIMarshalManagedToNativePrinter(Generator, ctx); |
||||
param.Visit(marshal); |
||||
|
||||
if (string.IsNullOrEmpty(marshal.Return)) |
||||
return null; |
||||
|
||||
if (!string.IsNullOrWhiteSpace(marshal.Support)) |
||||
WriteLine(marshal.Support); |
||||
|
||||
WriteLine("auto {0} = {1};", argName, marshal.Return); |
||||
@params.Add(argName); |
||||
} |
||||
} |
||||
|
||||
return @params; |
||||
} |
||||
|
||||
public void GenerateFunctionParams(Function function, List<string> @params) |
||||
{ |
||||
for (var i = 0; i < @params.Count; ++i) |
||||
{ |
||||
var param = @params[i]; |
||||
Write(param); |
||||
|
||||
if (i < @params.Count - 1) |
||||
Write(", "); |
||||
} |
||||
} |
||||
|
||||
public void GenerateDebug(Declaration decl) |
||||
{ |
||||
if (Options.OutputDebug && !String.IsNullOrWhiteSpace(decl.DebugText)) |
||||
WriteLine("// DEBUG: " + decl.DebugText); |
||||
} |
||||
|
||||
public override string FileExtension { get { return "cpp"; } } |
||||
} |
||||
} |
||||
@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using Cxxi.Generators; |
||||
|
||||
namespace Cxxi.Templates.CSharp |
||||
{ |
||||
class CSharpTypePrinter : ITypeVisitor<string> |
||||
{ |
||||
public CSharpTypePrinter() |
||||
{ |
||||
} |
||||
|
||||
public string VisitTagType(TagType tag, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitArrayType(ArrayType array, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
|
||||
// C# only supports fixed arrays in unsafe sections
|
||||
// and they are constrained to a set of built-in types.
|
||||
|
||||
//return string.Format("{0}[]", Type);
|
||||
} |
||||
|
||||
public string VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
|
||||
//string args = string.Empty;
|
||||
|
||||
//if (Arguments.Count > 0)
|
||||
// args = ToArgumentString(hasNames: false);
|
||||
|
||||
//if (ReturnType.IsPrimitiveType(PrimitiveType.Void))
|
||||
//{
|
||||
// if (!string.IsNullOrEmpty(args))
|
||||
// args = string.Format("<{0}>", args);
|
||||
// return string.Format("Action{0}", args);
|
||||
//}
|
||||
|
||||
//if (!string.IsNullOrEmpty(args))
|
||||
// args = string.Format(", {0}", args);
|
||||
|
||||
//return string.Format("Func<{0}{1}>",
|
||||
// ReturnType.ToCSharp(), args);
|
||||
} |
||||
|
||||
public string VisitPointerType(PointerType pointer, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
|
||||
//if (Pointee is FunctionType)
|
||||
//{
|
||||
// var function = Pointee as FunctionType;
|
||||
// return function.ToCSharp();
|
||||
//}
|
||||
|
||||
//if (Pointee is TagType)
|
||||
// return Pointee.ToCSharp();
|
||||
|
||||
//return "IntPtr";
|
||||
|
||||
//return string.Format("{0}{1}",
|
||||
// Pointee.ToCSharp(), ConvertModifierToString(Modifier));
|
||||
} |
||||
|
||||
public string VisitMemberPointerType(MemberPointerType member, |
||||
TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitTypedefType(TypedefType typedef, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string VisitDeclaration(Declaration decl, TypeQualifiers quals) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string GetArgumentString(Parameter arg, bool hasName) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
|
||||
//if (hasName && !string.IsNullOrEmpty(Name))
|
||||
// return string.Format("{0} {1}", Type.ToCSharp(), Name);
|
||||
//else
|
||||
// return Type.ToCSharp();
|
||||
} |
||||
} |
||||
|
||||
public class CSharpModule : TextTemplate |
||||
{ |
||||
// 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 override string FileExtension { get { return "cs"; } } |
||||
|
||||
protected override void Generate() |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,261 @@
@@ -0,0 +1,261 @@
|
||||
<#@ template debug="true" language="C#" inherits="Cxxi.Templates.TextTemplate" #> |
||||
<#@ 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.Enums.Count; ++i) |
||||
{ |
||||
var E = Module.Enums[i]; |
||||
if (E.Ignore) continue; |
||||
|
||||
GenerateEnum(E); |
||||
NeedsNewline = true; |
||||
if (i < Module.Enums.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the typedef declarations for the module. |
||||
for(int i = 0; i < Module.Typedefs.Count; ++i) |
||||
{ |
||||
var T = Module.Typedefs[i]; |
||||
if (T.Ignore) continue; |
||||
|
||||
GenerateTypedef(T); |
||||
NeedsNewline = true; |
||||
|
||||
if (i < Module.Typedefs.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the struct/class declarations for the module. |
||||
for(int i = 0; i < Module.Classes.Count; ++i) |
||||
{ |
||||
var C = Module.Classes[i]; |
||||
if (C.Ignore) continue; |
||||
|
||||
GenerateClass(C); |
||||
NeedsNewline = true; |
||||
if (i < Module.Classes.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
if (Module.HasFunctions) |
||||
{ |
||||
WriteLine("public partial class " + SafeIdentifier(Library.Name)); |
||||
WriteLine("{"); |
||||
PushIndent(DefaultIndent); |
||||
} |
||||
|
||||
// Generate all the function declarations for the module. |
||||
foreach(var E in Module.Functions) |
||||
{ |
||||
GenerateFunction(E); |
||||
} |
||||
|
||||
if (Module.HasFunctions) |
||||
{ |
||||
PopIndent(); |
||||
WriteLine("}"); |
||||
} |
||||
|
||||
PopIndent(); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateDeclarationCommon(Declaration T) |
||||
{ |
||||
GenerateSummary(T.BriefComment); |
||||
GenerateDebug(T); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateClass(Class C) |
||||
{ |
||||
if(C.Ignore) return; |
||||
GenerateDeclarationCommon(C); |
||||
|
||||
if (C.IsUnion) |
||||
WriteLine("[StructLayout(LayoutKind.Explicit)]"); |
||||
Write("public unsafe "); |
||||
|
||||
if (C.IsAbstract) |
||||
Write("abstract "); |
||||
|
||||
Write("class {0}", SafeIdentifier(C.Name)); |
||||
|
||||
if (C.HasBase) |
||||
Write(" : {0}", SafeIdentifier(C.Bases[0].Class.Name)); |
||||
|
||||
WriteLine(String.Empty); |
||||
WriteLine("{"); |
||||
|
||||
if (!C.IsOpaque) |
||||
{ |
||||
PushIndent(DefaultIndent); |
||||
foreach(var F in C.Fields) |
||||
{ |
||||
if (F.Ignore == true) continue; |
||||
|
||||
GenerateDeclarationCommon(F); |
||||
if (C.IsUnion) |
||||
WriteLine("[FieldOffset({0})]", F.Offset); |
||||
WriteLine("public {0} {1};", F.Type, SafeIdentifier(F.Name)); |
||||
} |
||||
PopIndent(); |
||||
} |
||||
|
||||
WriteLine("}"); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateTypedef(TypedefDecl T) |
||||
{ |
||||
if(T.Ignore) return; |
||||
GenerateDeclarationCommon(T); |
||||
|
||||
FunctionType func; |
||||
TagType tag; |
||||
|
||||
if (T.Type.IsPointerToPrimitiveType(PrimitiveType.Void) |
||||
|| T.Type.IsPointerTo<TagType>(out tag)) |
||||
{ |
||||
WriteLine("public class " + SafeIdentifier(T.Name) + @" { }"); |
||||
WriteLine(""); |
||||
} |
||||
else if(T.Type.IsPointerTo<FunctionType>(out func)) |
||||
{ |
||||
//WriteLine("public {0};", |
||||
// string.Format(func.ToDelegateString(), SafeIdentifier(T.Name))); |
||||
} |
||||
else if (T.Type.IsEnumType()) |
||||
{ |
||||
// Already handled in the parser. |
||||
} |
||||
else |
||||
{ |
||||
Console.WriteLine("Unhandled typedef type: {0}", T); |
||||
} |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateFunction(Function F) |
||||
{ |
||||
if(F.Ignore) return; |
||||
GenerateDeclarationCommon(F); |
||||
#> |
||||
[DllImport("<#= SafeIdentifier(Library.Native) #>.dll", |
||||
CallingConvention = CallingConvention.<#= F.ToCSharpCallConv() #>, |
||||
EntryPoint="<#= F.Mangled #>")] |
||||
public unsafe 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(Declaration decl) |
||||
{ |
||||
if(Options.OutputDebug && !String.IsNullOrWhiteSpace(decl.DebugText)) |
||||
WriteLine("// DEBUG: " + decl.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; |
||||
GenerateDeclarationCommon(E); |
||||
|
||||
if(E.Modifiers.HasFlag(Enumeration.EnumModifiers.Flags)) |
||||
WriteLine("[Flags]"); |
||||
#> |
||||
public enum <#= SafeIdentifier(E.Name) #> |
||||
<#+ |
||||
if(E.BuiltinType.Type != PrimitiveType.Int32) |
||||
WriteLine(" : {0}", E.BuiltinType.Type); |
||||
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,94 @@
@@ -0,0 +1,94 @@
|
||||
using Cxxi.Generators.CLI; |
||||
using Cxxi.Types; |
||||
using System.IO; |
||||
|
||||
namespace Cxxi.Generators |
||||
{ |
||||
public enum LanguageGeneratorKind |
||||
{ |
||||
CPlusPlusCLI, |
||||
CSharp |
||||
} |
||||
|
||||
public interface ILanguageGenerator |
||||
{ |
||||
Options Options { get; set; } |
||||
Library Library { get; set; } |
||||
ILibrary Transform { get; set; } |
||||
Generator Generator { get; set; } |
||||
|
||||
bool Generate(TranslationUnit unit); |
||||
} |
||||
|
||||
public partial class Generator |
||||
{ |
||||
public Options Options; |
||||
public Library Library; |
||||
public ILibrary LibraryTransform; |
||||
public TypeDatabase TypeDatabase; |
||||
|
||||
public Generator(Options options, Library library, ILibrary libraryTransform) |
||||
{ |
||||
this.Options = options; |
||||
this.Library = library; |
||||
this.LibraryTransform = libraryTransform; |
||||
|
||||
TypeDatabase = new TypeDatabase(); |
||||
TypeDatabase.SetupTypeMaps(); |
||||
} |
||||
|
||||
public void Generate() |
||||
{ |
||||
var generator = CreateLanguageGenerator(Options.Template); |
||||
|
||||
if (!Directory.Exists(Options.OutputDir)) |
||||
Directory.CreateDirectory(Options.OutputDir); |
||||
|
||||
// Process everything in the global namespace for now.
|
||||
foreach (var module in Library.TranslationUnits) |
||||
{ |
||||
if (module.ExplicityIgnored || !module.HasDeclarations) |
||||
continue; |
||||
|
||||
if (module.IsSystemHeader) |
||||
continue; |
||||
|
||||
// Generate the target code.
|
||||
generator.Generate(module); |
||||
} |
||||
} |
||||
|
||||
ILanguageGenerator CreateLanguageGenerator(LanguageGeneratorKind kind) |
||||
{ |
||||
ILanguageGenerator generator = null; |
||||
|
||||
switch (kind) |
||||
{ |
||||
case LanguageGeneratorKind.CPlusPlusCLI: |
||||
generator = new CLIGenerator(this); |
||||
break; |
||||
case LanguageGeneratorKind.CSharp: |
||||
//generator = new CSharpGenerator();
|
||||
break; |
||||
} |
||||
|
||||
generator.Options = Options; |
||||
generator.Library = Library; |
||||
generator.Transform = LibraryTransform; |
||||
|
||||
return generator; |
||||
} |
||||
|
||||
ILanguageGenerator CreateLanguageGenerator(string kind) |
||||
{ |
||||
switch (kind) |
||||
{ |
||||
default: |
||||
case "cli": |
||||
return CreateLanguageGenerator(LanguageGeneratorKind.CPlusPlusCLI); |
||||
case "cs": |
||||
return CreateLanguageGenerator(LanguageGeneratorKind.CSharp); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
namespace Cxxi.Generators |
||||
{ |
||||
public abstract class TextTemplate |
||||
{ |
||||
private const uint DefaultIndent = 4; |
||||
private const uint MaxIndent = 80; |
||||
|
||||
public Generator Generator { get; set; } |
||||
public Options Options { get; set; } |
||||
public Library Library { get; set; } |
||||
public ILibrary Transform; |
||||
public TranslationUnit Module { get; set; } |
||||
public abstract string FileExtension { get; } |
||||
|
||||
protected abstract void Generate(); |
||||
|
||||
protected StringBuilder Builder; |
||||
protected Stack<uint> CurrentIndent; |
||||
|
||||
private bool isStartOfLine; |
||||
|
||||
protected TextTemplate() |
||||
{ |
||||
Builder = new StringBuilder(); |
||||
CurrentIndent = new Stack<uint>(); |
||||
isStartOfLine = true; |
||||
} |
||||
|
||||
public void Write(string msg, params object[] args) |
||||
{ |
||||
if (isStartOfLine) |
||||
Builder.Append(new string(' ', (int)CurrentIndent.Sum(u => u))); |
||||
|
||||
if (args.Length > 0) |
||||
msg = string.Format(msg, args); |
||||
|
||||
if (msg.Length > 0) |
||||
isStartOfLine = false; |
||||
|
||||
Builder.Append(msg); |
||||
} |
||||
|
||||
public void WriteLine(string msg, params object[] args) |
||||
{ |
||||
Write(msg, args); |
||||
NewLine(); |
||||
} |
||||
|
||||
public void NewLine() |
||||
{ |
||||
Builder.AppendLine(string.Empty); |
||||
isStartOfLine = true; |
||||
} |
||||
|
||||
public void PushIndent(uint indent = DefaultIndent) |
||||
{ |
||||
CurrentIndent.Push(indent); |
||||
} |
||||
|
||||
public void PopIndent() |
||||
{ |
||||
CurrentIndent.Pop(); |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
Builder.Clear(); |
||||
Generate(); |
||||
return Builder.ToString(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,34 +0,0 @@
@@ -1,34 +0,0 @@
|
||||
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; |
||||
} |
||||
} |
||||
@ -1,79 +0,0 @@
@@ -1,79 +0,0 @@
|
||||
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
|
||||
} |
||||
} |
||||
} |
||||
@ -1,68 +0,0 @@
@@ -1,68 +0,0 @@
|
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Transform the Clang library declarations to something more .NET friendly.
|
||||
/// </summary>
|
||||
class ClangTransforms : LibraryTransform |
||||
{ |
||||
public void Preprocess(Generator g) |
||||
{ |
||||
//g.SetNameOfEnumWithMatchingItem("SDL_LOG_CATEGORY_CUSTOM", "LogCategory");
|
||||
g.RemovePrefix("CX"); |
||||
g.RemovePrefix("clang_"); |
||||
g.RenameWithPattern("^_", string.Empty, RenameFlags.Declaration); |
||||
|
||||
// Clean up types
|
||||
g.FindClass("CXString").IsOpaque = true; |
||||
g.FindClass("CXSourceLocation").IsOpaque = true; |
||||
g.FindClass("CXSourceRange").IsOpaque = true; |
||||
g.FindClass("CXCursor").IsOpaque = true; |
||||
g.FindClass("CXType").IsOpaque = true; |
||||
g.FindClass("CXToken").IsOpaque = true; |
||||
g.FindClass("CXIdxLoc").IsOpaque = true; |
||||
g.FindClass("CXTranslationUnitImpl").IsOpaque = true; |
||||
|
||||
// Clean up enums
|
||||
g.RemovePrefixEnumItem("ChildVisit_"); |
||||
g.RemovePrefixEnumItem("Comment_"); |
||||
g.RemovePrefixEnumItem("Availability_"); |
||||
g.RemovePrefixEnumItem("GlobalOpt_"); |
||||
g.RemovePrefixEnumItem("Diagnostic_"); |
||||
g.RemovePrefixEnumItem("LoadDiag_"); |
||||
g.RemovePrefixEnumItem("TranslationUnit_"); |
||||
g.RemovePrefixEnumItem("SaveTranslationUnit_"); |
||||
g.RemovePrefixEnumItem("SaveError_"); |
||||
g.RemovePrefixEnumItem("TranslationUnit_"); |
||||
g.RemovePrefixEnumItem("Reparse_"); |
||||
g.RemovePrefixEnumItem("TUResourceUsage_"); |
||||
g.RemovePrefixEnumItem("Cursor_"); |
||||
g.RemovePrefixEnumItem("Linkage_"); |
||||
g.RemovePrefixEnumItem("Language_"); |
||||
g.RemovePrefixEnumItem("Type_"); |
||||
g.RemovePrefixEnumItem("CallingConv_"); |
||||
g.RemovePrefixEnumItem("CommentInlineCommandRenderKind_"); |
||||
g.RemovePrefixEnumItem("CommentParamPassDirection_"); |
||||
g.RemovePrefixEnumItem("NameRange_"); |
||||
g.RemovePrefixEnumItem("Token_"); |
||||
g.RemovePrefixEnumItem("CompletionChunk_"); |
||||
g.RemovePrefixEnumItem("CodeComplete_"); |
||||
g.RemovePrefixEnumItem("CompletionContext_"); |
||||
g.RemovePrefixEnumItem("Visit_"); |
||||
g.RemovePrefixEnumItem("IdxEntity_"); |
||||
g.RemovePrefixEnumItem("IdxEntityLang_"); |
||||
g.RemovePrefixEnumItem("IdxAttr_"); |
||||
g.RemovePrefixEnumItem("IdxObjCContainer_"); |
||||
g.RemovePrefixEnumItem("IdxEntityRef_"); |
||||
g.RemovePrefixEnumItem("IndexOpt_"); |
||||
g.RemovePrefixEnumItem("IdxObjCContainer_"); |
||||
} |
||||
|
||||
public void Postprocess(Generator g) |
||||
{ |
||||
g.FindEnum("CompletionContext").SetFlags(); |
||||
g.FindClass("String").Name = "CXString"; |
||||
//gen.SetNameOfEnumWithName("LOG_CATEGORY", "LogCategory");
|
||||
} |
||||
} |
||||
} |
||||
@ -1,60 +0,0 @@
@@ -1,60 +0,0 @@
|
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Transform the SDL library declarations to something more .NET friendly.
|
||||
/// </summary>
|
||||
class SDLTransforms : LibraryTransform |
||||
{ |
||||
public void Preprocess(Generator g) |
||||
{ |
||||
g.IgnoreEnumWithMatchingItem("SDL_FALSE"); |
||||
g.IgnoreEnumWithMatchingItem("DUMMY_ENUM_VALUE"); |
||||
|
||||
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("InputState", "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.IgnoreModuleWithName("SDL_error");
|
||||
|
||||
g.IgnoreEnumWithMatchingItem("SDL_ENOMEM"); |
||||
g.IgnoreFunctionWithName("SDL_Error"); |
||||
|
||||
g.RemovePrefix("SDL_"); |
||||
g.RemovePrefix("SCANCODE_"); |
||||
g.RemovePrefix("SDLK_"); |
||||
g.RemovePrefix("KMOD_"); |
||||
g.RemovePrefix("LOG_CATEGORY_"); |
||||
} |
||||
|
||||
public void Postprocess(Generator g) |
||||
{ |
||||
g.SetNameOfEnumWithName("PIXELTYPE", "PixelType"); |
||||
g.SetNameOfEnumWithName("BITMAPORDER", "BitmapOrder"); |
||||
g.SetNameOfEnumWithName("PACKEDORDER", "PackedOrder"); |
||||
g.SetNameOfEnumWithName("ARRAYORDER", "ArrayOrder"); |
||||
g.SetNameOfEnumWithName("PACKEDLAYOUT", "PackedLayout"); |
||||
g.SetNameOfEnumWithName("PIXELFORMAT", "PixelFormats"); |
||||
g.SetNameOfEnumWithName("assert_state", "AssertState"); |
||||
g.SetNameOfClassWithName("assert_data", "AssertData"); |
||||
g.SetNameOfEnumWithName("eventaction", "EventAction"); |
||||
|
||||
//gen.SetNameOfEnumWithName("LOG_CATEGORY", "LogCategory");
|
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,263 @@
@@ -0,0 +1,263 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Text.RegularExpressions; |
||||
using Cxxi.Generators; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
[AttributeUsage(AttributeTargets.Class)] |
||||
public class LibraryTransformAttribute : Attribute |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Used to massage the library types into something more .NET friendly.
|
||||
/// </summary>
|
||||
public interface ILibrary |
||||
{ |
||||
/// <summary>
|
||||
/// Do transformations that should happen before processing here.
|
||||
/// </summary>
|
||||
void Preprocess(LibraryHelpers g); |
||||
|
||||
/// <summary>
|
||||
/// Do transformations that should happen after processing here.
|
||||
/// </summary>
|
||||
void Postprocess(LibraryHelpers g); |
||||
|
||||
/// <summary>
|
||||
/// Setup your passes here.
|
||||
/// </summary>
|
||||
/// <param name="passes"></param>
|
||||
void SetupPasses(PassBuilder passes); |
||||
|
||||
/// <summary>
|
||||
/// Called to generate text at the start of the text template.
|
||||
/// </summary>
|
||||
/// <param name="template"></param>
|
||||
void GenerateStart(TextTemplate template); |
||||
|
||||
/// <summary>
|
||||
/// Called to generate text after the generation of namespaces.
|
||||
/// </summary>
|
||||
/// <param name="template"></param>
|
||||
void GenerateAfterNamespaces(TextTemplate template); |
||||
} |
||||
|
||||
public enum InlineMethods |
||||
{ |
||||
Present, |
||||
Unavailable |
||||
} |
||||
|
||||
public class LibraryHelpers |
||||
{ |
||||
private Library Library { get; set; } |
||||
|
||||
public LibraryHelpers(Library library) |
||||
{ |
||||
Library = library; |
||||
} |
||||
|
||||
#region Enum Helpers
|
||||
|
||||
public Enumeration FindEnum(string name) |
||||
{ |
||||
foreach (var unit in Library.TranslationUnits) |
||||
{ |
||||
var @enum = unit.FindEnum(name); |
||||
if (@enum != null) |
||||
return @enum; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public void IgnoreEnumWithMatchingItem(string pattern) |
||||
{ |
||||
Enumeration @enum = GetEnumWithMatchingItem(pattern); |
||||
if (@enum != null) |
||||
@enum.ExplicityIgnored = true; |
||||
} |
||||
|
||||
public void SetNameOfEnumWithMatchingItem(string pattern, string name) |
||||
{ |
||||
Enumeration @enum = GetEnumWithMatchingItem(pattern); |
||||
if (@enum != null) |
||||
@enum.Name = name; |
||||
} |
||||
|
||||
public void SetNameOfEnumWithName(string enumName, string name) |
||||
{ |
||||
Enumeration @enum = FindEnum(enumName); |
||||
if (@enum != null) |
||||
@enum.Name = name; |
||||
} |
||||
|
||||
public Enumeration GetEnumWithMatchingItem(string pattern) |
||||
{ |
||||
foreach (var module in Library.TranslationUnits) |
||||
{ |
||||
Enumeration @enum = module.FindEnumWithItem(pattern); |
||||
if (@enum == null) continue; |
||||
return @enum; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public Enumeration.Item GenerateEnumItemFromMacro(MacroDefinition macro) |
||||
{ |
||||
var item = new Enumeration.Item |
||||
{ |
||||
Name = macro.Name, |
||||
Expression = macro.Expression, |
||||
Value = ParseMacroExpression(macro.Expression) |
||||
}; |
||||
|
||||
return item; |
||||
} |
||||
|
||||
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 GenerateEnumFromMacros(string name, params string[] macros) |
||||
{ |
||||
var @enum = new Enumeration { Name = name }; |
||||
|
||||
var pattern = string.Join("|", macros); |
||||
var regex = new Regex(pattern); |
||||
|
||||
foreach (var unit in Library.TranslationUnits) |
||||
{ |
||||
foreach (var macro in unit.Macros) |
||||
{ |
||||
var match = regex.Match(macro.Name); |
||||
if (!match.Success) continue; |
||||
|
||||
var item = GenerateEnumItemFromMacro(macro); |
||||
@enum.AddItem(item); |
||||
} |
||||
|
||||
if (@enum.Items.Count > 0) |
||||
{ |
||||
unit.Enums.Add(@enum); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return @enum; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Class Helpers
|
||||
|
||||
public Class FindClass(string name) |
||||
{ |
||||
foreach (var module in Library.TranslationUnits) |
||||
{ |
||||
var @class = module.FindClass(name); |
||||
if (@class != null) |
||||
return @class; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public void SetClassBindName(string className, string name) |
||||
{ |
||||
Class @class = FindClass(className); |
||||
if (@class != null) |
||||
@class.Name = name; |
||||
} |
||||
|
||||
public void SetClassAsValueType(string className) |
||||
{ |
||||
Class @class = FindClass(className); |
||||
if (@class != null) |
||||
@class.Type = ClassType.ValueType; |
||||
} |
||||
|
||||
public void IgnoreClassWithName(string name) |
||||
{ |
||||
Class @class = FindClass(name); |
||||
if (@class != null) |
||||
@class.ExplicityIgnored = true; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Function Helpers
|
||||
|
||||
public Function FindFunction(string name) |
||||
{ |
||||
foreach (var module in Library.TranslationUnits) |
||||
{ |
||||
var function = module.FindFunction(name); |
||||
if (function != null) |
||||
return function; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public void IgnoreFunctionWithName(string name) |
||||
{ |
||||
Function function = FindFunction(name); |
||||
if (function != null) |
||||
function.ExplicityIgnored = true; |
||||
} |
||||
|
||||
public void IgnoreClassMethodWithName(string className, string name) |
||||
{ |
||||
Class @class = FindClass(className); |
||||
|
||||
if (@class == null) |
||||
return; |
||||
|
||||
var method = @class.Methods.Find(m => m.Name == name); |
||||
|
||||
if (method == null) |
||||
return; |
||||
|
||||
method.ExplicityIgnored = true; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Module Helpers
|
||||
|
||||
public void IgnoreModulessWithName(string pattern) |
||||
{ |
||||
var modules = Library.TranslationUnits.FindAll(m => |
||||
Regex.Match(m.FilePath, pattern).Success); |
||||
|
||||
foreach (var module in modules) |
||||
{ |
||||
module.ExplicityIgnored = true; |
||||
} |
||||
} |
||||
|
||||
#endregion
|
||||
} |
||||
} |
||||
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
|
||||
namespace Cxxi.Passes |
||||
{ |
||||
/// <summary>
|
||||
/// Used to provide different types of code transformation on a module
|
||||
/// declarations and types before the code generation process is started.
|
||||
/// </summary>
|
||||
public abstract class TranslationUnitPass |
||||
{ |
||||
public Library Library { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Processes a library.
|
||||
/// </summary>
|
||||
public virtual bool ProcessLibrary(Library library) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes a declaration.
|
||||
/// </summary>
|
||||
public virtual bool ProcessDeclaration(Declaration decl) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes a class.
|
||||
/// </summary>
|
||||
public virtual bool ProcessClass(Class @class) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes a field.
|
||||
/// </summary>
|
||||
public virtual bool ProcessField(Field field) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes a function declaration.
|
||||
/// </summary>
|
||||
public virtual bool ProcessFunction(Function function) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes a method declaration.
|
||||
/// </summary>
|
||||
public virtual bool ProcessMethod(Method method) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes an enum declaration.
|
||||
/// </summary>
|
||||
public virtual bool ProcessEnum(Enumeration @enum) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes an enum item.
|
||||
/// </summary>
|
||||
public virtual bool ProcessEnumItem(Enumeration.Item item) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using Cxxi.Passes; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// This class is used to build passes that will be run against the AST
|
||||
/// that comes from C++.
|
||||
/// </summary>
|
||||
public class PassBuilder |
||||
{ |
||||
public List<TranslationUnitPass> Passes { get; set; } |
||||
|
||||
public PassBuilder() |
||||
{ |
||||
Passes = new List<TranslationUnitPass>(); |
||||
} |
||||
|
||||
public void AddPass(TranslationUnitPass pass) |
||||
{ |
||||
Passes.Add(pass); |
||||
} |
||||
|
||||
#region Operation Helpers
|
||||
|
||||
public void RenameWithPattern(string pattern, string replacement, RenameTargets targets) |
||||
{ |
||||
AddPass(new RegexRenamePass(pattern, replacement, targets)); |
||||
} |
||||
|
||||
public void RemovePrefix(string prefix) |
||||
{ |
||||
AddPass(new RegexRenamePass("^" + prefix, String.Empty)); |
||||
} |
||||
|
||||
public void RemovePrefixEnumItem(string prefix) |
||||
{ |
||||
AddPass(new RegexRenamePass("^" + prefix, String.Empty, RenameTargets.EnumItem)); |
||||
} |
||||
|
||||
public void RenameDeclsCase(RenameTargets targets, RenameCasePattern pattern) |
||||
{ |
||||
AddPass(new CaseRenamePass(targets, pattern)); |
||||
} |
||||
|
||||
#endregion
|
||||
} |
||||
} |
||||
@ -1,158 +0,0 @@
@@ -1,158 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using Mono.Options; |
||||
using Cxxi; |
||||
|
||||
public class Options |
||||
{ |
||||
public Options() |
||||
{ |
||||
IncludeDirs = new List<string>(); |
||||
Headers = new List<string>(); |
||||
} |
||||
|
||||
public bool Verbose = false; |
||||
public bool ShowHelpText = false; |
||||
public bool OutputDebug = false; |
||||
public string OutputNamespace; |
||||
public string OutputDir; |
||||
public string Library; |
||||
public List<string> IncludeDirs; |
||||
public List<string> Headers; |
||||
} |
||||
|
||||
class Program |
||||
{ |
||||
Library library; |
||||
Options options; |
||||
|
||||
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.Add(v) }, |
||||
// Generator options
|
||||
{ "ns|namespace=", v => options.OutputNamespace = v }, |
||||
{ "o|outdir=", v => options.OutputDir = v }, |
||||
{ "debug", v => options.OutputDebug = true }, |
||||
{ "lib|library=", v => options.Library = v }, |
||||
// 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) |
||||
{ |
||||
Console.WriteLine("Error parsing the command line."); |
||||
ShowHelp(set); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public void GenerateCode(LibraryTransform transform) |
||||
{ |
||||
Console.WriteLine("Generating wrapper code..."); |
||||
|
||||
if (library.Modules.Count > 0) |
||||
{ |
||||
var gen = new Generator(library, options); |
||||
|
||||
transform.Preprocess(gen); |
||||
|
||||
gen.Process(); |
||||
|
||||
transform.Postprocess(gen); |
||||
|
||||
gen.Generate(); |
||||
} |
||||
} |
||||
|
||||
public void ParseCode() |
||||
{ |
||||
var Opts = new ParserOptions(); |
||||
Opts.Library = library; |
||||
Opts.Verbose = false; |
||||
Opts.IncludeDirs = options.IncludeDirs; |
||||
|
||||
Console.WriteLine("Parsing native code..."); |
||||
|
||||
foreach (var file in options.Headers) |
||||
{ |
||||
var path = String.Empty; |
||||
|
||||
try |
||||
{ |
||||
path = Path.GetFullPath(file); |
||||
} |
||||
catch (ArgumentException) |
||||
{ |
||||
Console.WriteLine("Invalid path '" + file + "'."); |
||||
continue; |
||||
} |
||||
|
||||
var module = new Module(path); |
||||
Opts.FileName = path; |
||||
|
||||
if (!ClangParser.Parse(Opts)) |
||||
{ |
||||
Console.WriteLine(" Could not parse '" + file + "'."); |
||||
continue; |
||||
} |
||||
|
||||
Console.WriteLine(" Parsed '" + file + "'."); |
||||
} |
||||
} |
||||
|
||||
public void Run(String[] args) |
||||
{ |
||||
options = new Options(); |
||||
|
||||
if (!ParseCommandLineOptions(args)) |
||||
return; |
||||
|
||||
library = new Library(options.OutputNamespace, options.Library); |
||||
|
||||
ParseCode(); |
||||
|
||||
//var transform = new SDLTransforms();
|
||||
var transform = new ClangTransforms(); |
||||
|
||||
GenerateCode(transform); |
||||
} |
||||
|
||||
static void Main(String[] args) |
||||
{ |
||||
var program = new Program(); |
||||
program.Run(args); |
||||
|
||||
Console.ReadKey(); |
||||
} |
||||
} |
||||
@ -1,246 +0,0 @@
@@ -1,246 +0,0 @@
|
||||
<#@ 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.Enums.Count; ++i) |
||||
{ |
||||
var E = Module.Enums[i]; |
||||
if (E.Ignore) continue; |
||||
|
||||
GenerateEnum(E); |
||||
NeedsNewline = true; |
||||
if (i < Module.Enums.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the typedef declarations for the module. |
||||
for(int i = 0; i < Module.Typedefs.Count; ++i) |
||||
{ |
||||
var T = Module.Typedefs[i]; |
||||
if (T.Ignore) continue; |
||||
|
||||
GenerateTypedef(T); |
||||
NeedsNewline = true; |
||||
if (i < Module.Typedefs.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
NeedsNewline = false; |
||||
|
||||
// Generate all the struct/class declarations for the module. |
||||
for(int i = 0; i < Module.Classes.Count; ++i) |
||||
{ |
||||
var C = Module.Classes[i]; |
||||
if (C.Ignore) continue; |
||||
|
||||
GenerateClass(C); |
||||
NeedsNewline = true; |
||||
if (i < Module.Classes.Count - 1) |
||||
WriteLine(""); |
||||
} |
||||
|
||||
if (NeedsNewline) |
||||
WriteLine(""); |
||||
|
||||
if (Module.HasFunctions) |
||||
{ |
||||
WriteLine("public partial class " + SafeIdentifier(Library.Name)); |
||||
WriteLine("{"); |
||||
PushIndent(DefaultIndent); |
||||
} |
||||
|
||||
// Generate all the function declarations for the module. |
||||
foreach(var E in Module.Functions) |
||||
{ |
||||
GenerateFunction(E); |
||||
} |
||||
|
||||
if (Module.HasFunctions) |
||||
{ |
||||
PopIndent(); |
||||
WriteLine("}"); |
||||
} |
||||
|
||||
PopIndent(); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateDeclarationCommon(Declaration T) |
||||
{ |
||||
GenerateSummary(T.BriefComment); |
||||
GenerateDebug(T); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateClass(Class C) |
||||
{ |
||||
if(C.Ignore) return; |
||||
GenerateDeclarationCommon(C); |
||||
|
||||
if (C.IsUnion) |
||||
WriteLine("[StructLayout(LayoutKind.Explicit)]"); |
||||
Write("public unsafe "); |
||||
|
||||
if (C.IsAbstract) |
||||
Write("abstract "); |
||||
|
||||
Write("class {0}", SafeIdentifier(C.Name)); |
||||
|
||||
if (C.HasBase) |
||||
Write(" : {0}", SafeIdentifier(C.Bases[0].Class.Name)); |
||||
|
||||
WriteLine(String.Empty); |
||||
WriteLine("{"); |
||||
|
||||
if (!C.IsOpaque) |
||||
{ |
||||
PushIndent(DefaultIndent); |
||||
foreach(var F in C.Fields) |
||||
{ |
||||
GenerateDeclarationCommon(F); |
||||
if (C.IsUnion) |
||||
WriteLine("[FieldOffset({0})]", F.Offset); |
||||
WriteLine("public {0} {1};", F.Type.ToCSharp(), SafeIdentifier(F.Name)); |
||||
} |
||||
PopIndent(); |
||||
} |
||||
|
||||
WriteLine("}"); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateTypedef(Typedef T) |
||||
{ |
||||
if(T.Ignore) return; |
||||
GenerateDeclarationCommon(T); |
||||
|
||||
FunctionType func; |
||||
|
||||
if (T.Type.IsPointerToPrimitiveType(PrimitiveType.Void)) |
||||
{ |
||||
WriteLine("public class " + SafeIdentifier(T.Name) + @" { }"); |
||||
WriteLine(""); |
||||
} |
||||
else if(T.Type.IsPointerTo<FunctionType>(out func)) |
||||
{ |
||||
WriteLine("public {0};", |
||||
string.Format(func.ToDelegateString(), SafeIdentifier(T.Name))); |
||||
} |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateFunction(Function F) |
||||
{ |
||||
if(F.Ignore) return; |
||||
GenerateDeclarationCommon(F); |
||||
#> |
||||
[DllImport("<#= SafeIdentifier(Library.Native) #>.dll")] |
||||
public unsafe static extern <#= F.ReturnType.ToCSharp() #> <#= SafeIdentifier(F.Name) #>(<#+ |
||||
for(int i = 0; i < F.Parameters.Count; ++i) |
||||
{ |
||||
var P = F.Parameters[i]; |
||||
Write("{0} {1}", P.Type.ToCSharp(), SafeIdentifier(P.Name)); |
||||
if (i < F.Parameters.Count - 1) |
||||
Write(", "); |
||||
} |
||||
#>); |
||||
<#+ |
||||
WriteLine(""); |
||||
} |
||||
#> |
||||
|
||||
<#+ |
||||
public void GenerateDebug(Declaration decl) |
||||
{ |
||||
if(Options.OutputDebug && !String.IsNullOrWhiteSpace(decl.DebugText)) |
||||
WriteLine("// DEBUG: " + decl.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; |
||||
GenerateDeclarationCommon(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(""); |
||||
#> |
||||
} |
||||
<#+ |
||||
} |
||||
#> |
||||
@ -1,313 +0,0 @@
@@ -1,313 +0,0 @@
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Globalization; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Used to massage the library types into something more .NET friendly.
|
||||
/// </summary>
|
||||
public interface LibraryTransform |
||||
{ |
||||
/// <summary>
|
||||
/// Do transformations that should happen before processing here.
|
||||
/// </summary>
|
||||
void Preprocess(Generator g); |
||||
|
||||
/// <summary>
|
||||
/// Do transformations that should happen after processing here.
|
||||
/// </summary>
|
||||
void Postprocess(Generator g); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Used to provide different types of code transformation on a module
|
||||
/// declarations and types before the code generation process is started.
|
||||
/// </summary>
|
||||
public abstract class ModuleTransform |
||||
{ |
||||
/// <summary>
|
||||
/// Processes a declaration.
|
||||
/// </summary>
|
||||
public virtual bool ProcessDeclaration(Declaration declaration) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes an enum.
|
||||
/// </summary>
|
||||
public virtual bool ProcessEnum(Enumeration @enum) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Processes an enum item.
|
||||
/// </summary>
|
||||
public virtual bool ProcessEnumItem(Enumeration.Item item) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
[Flags] |
||||
public enum RenameFlags |
||||
{ |
||||
Function, |
||||
Record, |
||||
Field, |
||||
Enum, |
||||
EnumItem, |
||||
Declaration = Function | Record | Field | Enum | EnumItem, |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Renames a declaration based on a regular expression pattern.
|
||||
/// </summary>
|
||||
public class RenameTransform : ModuleTransform |
||||
{ |
||||
public string Pattern; |
||||
public string Replacement; |
||||
public RenameFlags Flags = RenameFlags.Declaration; |
||||
|
||||
public RenameTransform(string pattern, string replacement) |
||||
{ |
||||
Pattern = pattern; |
||||
Replacement = replacement; |
||||
} |
||||
|
||||
public RenameTransform(string pattern, string replacement, RenameFlags flags) |
||||
: this(pattern, replacement) |
||||
{ |
||||
Flags = flags; |
||||
} |
||||
|
||||
public override bool ProcessDeclaration(Declaration type) |
||||
{ |
||||
if (!Flags.HasFlag(RenameFlags.Declaration)) |
||||
return false; |
||||
return Rename(ref type.Name); |
||||
} |
||||
|
||||
public override bool ProcessEnumItem(Enumeration.Item item) |
||||
{ |
||||
if (!Flags.HasFlag(RenameFlags.EnumItem)) |
||||
return false; |
||||
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 |
||||
{ |
||||
#region Transform Operations
|
||||
|
||||
public void RenameWithPattern(string pattern, string replacement, RenameFlags flags) |
||||
{ |
||||
Transformations.Add(new RenameTransform(pattern, replacement, flags)); |
||||
} |
||||
|
||||
public void RemovePrefix(string prefix) |
||||
{ |
||||
Transformations.Add(new RenameTransform("^"+prefix, String.Empty)); |
||||
} |
||||
|
||||
public void RemovePrefixEnumItem(string prefix) |
||||
{ |
||||
Transformations.Add(new RenameTransform("^"+prefix, String.Empty, RenameFlags.EnumItem)); |
||||
} |
||||
|
||||
public void RemoveType(Declaration type) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Enum Helpers
|
||||
|
||||
public Enumeration FindEnum(string name) |
||||
{ |
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
var @enum = module.FindEnum(name); |
||||
if (@enum != null) |
||||
return @enum; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
public void SetNameOfEnumWithName(string enumName, string name) |
||||
{ |
||||
Enumeration @enum = FindEnum(enumName); |
||||
if (@enum != null) |
||||
@enum.Name = name; |
||||
} |
||||
|
||||
public Enumeration GetEnumWithMatchingItem(string Pattern) |
||||
{ |
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
Enumeration @enum = module.FindEnumWithItem(Pattern); |
||||
if (@enum == null) continue; |
||||
return @enum; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
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.Enums.Add(@enum); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return @enum; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Class Helpers
|
||||
|
||||
public Class FindClass(string name) |
||||
{ |
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
var @class = module.FindClass(name); |
||||
if (@class != null) |
||||
return @class; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public void SetNameOfClassWithName(string className, string name) |
||||
{ |
||||
Class @class = FindClass(className); |
||||
if (@class != null) |
||||
@class.Name = name; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Function Helpers
|
||||
|
||||
public Function FindFunction(string name) |
||||
{ |
||||
foreach (var module in Library.Modules) |
||||
{ |
||||
var function = module.FindFunction(name); |
||||
if (function != null) |
||||
return function; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public void IgnoreFunctionWithName(string name) |
||||
{ |
||||
Function function = FindFunction(name); |
||||
if (function != null) |
||||
function.Ignore = true; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Module Helpers
|
||||
|
||||
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; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
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; |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,224 @@
@@ -0,0 +1,224 @@
|
||||
using System; |
||||
using System.Text; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
namespace Cxxi.Passes |
||||
{ |
||||
/// <summary>
|
||||
/// Base class for transform that perform renames of declarations.
|
||||
/// </summary>
|
||||
public abstract class RenamePass : TranslationUnitPass |
||||
{ |
||||
public RenameTargets Targets = RenameTargets.Any; |
||||
|
||||
protected RenamePass() |
||||
{ |
||||
} |
||||
|
||||
protected RenamePass(RenameTargets targets) |
||||
{ |
||||
Targets = targets; |
||||
} |
||||
} |
||||
|
||||
[Flags] |
||||
public enum RenameTargets |
||||
{ |
||||
Record, |
||||
Field, |
||||
Method, |
||||
Function, |
||||
Enum, |
||||
EnumItem, |
||||
Any = Function | Method | Record | Field | Enum | EnumItem, |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Renames a declaration based on a regular expression pattern.
|
||||
/// </summary>
|
||||
public class RegexRenamePass : RenamePass |
||||
{ |
||||
public string Pattern; |
||||
public string Replacement; |
||||
|
||||
public RegexRenamePass(string pattern, string replacement) |
||||
{ |
||||
Pattern = pattern; |
||||
Replacement = replacement; |
||||
} |
||||
|
||||
public RegexRenamePass(string pattern, string replacement, |
||||
RenameTargets targets) |
||||
: this(pattern, replacement) |
||||
{ |
||||
Targets = targets; |
||||
} |
||||
|
||||
public override bool ProcessDeclaration(Declaration decl) |
||||
{ |
||||
if (!Targets.HasFlag(RenameTargets.Any)) |
||||
return false; |
||||
|
||||
string newName; |
||||
if (Rename(decl.Name, out newName)) |
||||
{ |
||||
decl.Name = newName; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public override bool ProcessEnumItem(Enumeration.Item item) |
||||
{ |
||||
if (!Targets.HasFlag(RenameTargets.EnumItem)) |
||||
return false; |
||||
|
||||
string newName; |
||||
if (Rename(item.Name, out newName)) |
||||
{ |
||||
item.Name = newName; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public override bool ProcessField(Field field) |
||||
{ |
||||
if (!Targets.HasFlag(RenameTargets.Field)) |
||||
return false; |
||||
|
||||
string newName; |
||||
if (Rename(field.Name, out newName)) |
||||
{ |
||||
field.Name = newName; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
bool Rename(string name, out string newName) |
||||
{ |
||||
var replace = Regex.Replace(name, Pattern, Replacement); |
||||
|
||||
if (!name.Equals(replace)) |
||||
{ |
||||
newName = replace; |
||||
return true; |
||||
} |
||||
|
||||
newName = null; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public enum RenameCasePattern |
||||
{ |
||||
UpperCamelCase, |
||||
LowerCamelCase |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Renames a declaration based on a regular expression pattern.
|
||||
/// </summary>
|
||||
public class CaseRenamePass : RenamePass |
||||
{ |
||||
public RenameCasePattern Pattern; |
||||
|
||||
public CaseRenamePass(RenameTargets targets, RenameCasePattern pattern) |
||||
: base(targets) |
||||
{ |
||||
Pattern = pattern; |
||||
} |
||||
|
||||
private void Rename<T>(ref T decl) where T : Declaration |
||||
{ |
||||
switch (Pattern) |
||||
{ |
||||
case RenameCasePattern.LowerCamelCase: |
||||
decl.Name = ConvertCaseString(decl.Name, RenameCasePattern.LowerCamelCase); |
||||
break; |
||||
case RenameCasePattern.UpperCamelCase: |
||||
decl.Name = ConvertCaseString(decl.Name, RenameCasePattern.UpperCamelCase); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
public override bool ProcessDeclaration(Declaration decl) |
||||
{ |
||||
if (!Targets.HasFlag(RenameTargets.Any)) |
||||
return false; |
||||
|
||||
Rename(ref decl); |
||||
return true; |
||||
} |
||||
|
||||
public override bool ProcessFunction(Function function) |
||||
{ |
||||
if (!Targets.HasFlag(RenameTargets.Function)) |
||||
return false; |
||||
|
||||
Rename(ref function); |
||||
return true; |
||||
} |
||||
|
||||
public override bool ProcessField(Field field) |
||||
{ |
||||
if (!Targets.HasFlag(RenameTargets.Field)) |
||||
return false; |
||||
|
||||
Rename(ref field); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public override bool ProcessMethod(Method method) |
||||
{ |
||||
if (!Targets.HasFlag(RenameTargets.Method)) |
||||
return false; |
||||
|
||||
if (method.Kind != CXXMethodKind.Normal) |
||||
return false; |
||||
|
||||
Rename(ref method); |
||||
return true; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Converts the phrase to specified convention.
|
||||
/// </summary>
|
||||
/// <param name="phrase"></param>
|
||||
/// <param name="pattern">The cases.</param>
|
||||
/// <returns>string</returns>
|
||||
static string ConvertCaseString(string phrase, RenameCasePattern pattern) |
||||
{ |
||||
var splittedPhrase = phrase.Split(' ', '-', '.'); |
||||
var sb = new StringBuilder(); |
||||
|
||||
switch (pattern) |
||||
{ |
||||
case RenameCasePattern.LowerCamelCase: |
||||
sb.Append(splittedPhrase[0].ToLower()); |
||||
splittedPhrase[0] = string.Empty; |
||||
break; |
||||
case RenameCasePattern.UpperCamelCase: |
||||
sb = new StringBuilder(); |
||||
break; |
||||
} |
||||
|
||||
foreach (var s in splittedPhrase) |
||||
{ |
||||
var splittedPhraseChars = s.ToCharArray(); |
||||
if (splittedPhraseChars.Length > 0) |
||||
{ |
||||
var str = new String(splittedPhraseChars[0], 1); |
||||
splittedPhraseChars[0] = (str.ToUpper().ToCharArray())[0]; |
||||
} |
||||
sb.Append(new String(splittedPhraseChars)); |
||||
} |
||||
return sb.ToString(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,164 @@
@@ -0,0 +1,164 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace Cxxi.Passes |
||||
{ |
||||
public class Transform |
||||
{ |
||||
public Options Options; |
||||
public PassBuilder Passes; |
||||
|
||||
public void TransformLibrary(Library library) |
||||
{ |
||||
if (string.IsNullOrEmpty(library.Name)) |
||||
library.Name = string.Empty; |
||||
|
||||
// Process everything in the global namespace for now.
|
||||
foreach (var module in library.TranslationUnits) |
||||
TransformModule(module); |
||||
} |
||||
|
||||
string GetIncludePath(string filePath) |
||||
{ |
||||
string includePath = filePath; |
||||
|
||||
foreach (var path in Options.IncludeDirs) |
||||
{ |
||||
int idx = filePath.IndexOf(path, System.StringComparison.Ordinal); |
||||
if (idx == -1) continue; |
||||
|
||||
string inc = filePath.Substring(path.Length); |
||||
|
||||
if (inc.Length < includePath.Length) |
||||
includePath = inc; |
||||
} |
||||
|
||||
return includePath.TrimStart(new char[] { '\\', '/' }); |
||||
} |
||||
|
||||
void TransformModule(TranslationUnit unit) |
||||
{ |
||||
// Try to get an include path that works from the original include
|
||||
// directories paths.
|
||||
|
||||
unit.IncludePath = GetIncludePath(unit.FilePath); |
||||
|
||||
foreach (var @enum in unit.Enums) |
||||
TransformEnum(@enum); |
||||
|
||||
foreach (var function in unit.Functions) |
||||
TransformFunction(function); |
||||
|
||||
foreach (var @class in unit.Classes) |
||||
TransformClass(@class); |
||||
|
||||
foreach (var typedef in unit.Typedefs) |
||||
TransformTypedef(typedef); |
||||
} |
||||
|
||||
void TransformDeclaration(Declaration decl) |
||||
{ |
||||
foreach (var pass in Passes.Passes) |
||||
pass.ProcessDeclaration(decl); |
||||
} |
||||
|
||||
void TransformTypedef(TypedefDecl typedef) |
||||
{ |
||||
foreach (var pass in Passes.Passes) |
||||
pass.ProcessDeclaration(typedef); |
||||
} |
||||
|
||||
void TransformClass(Class @class) |
||||
{ |
||||
TransformDeclaration(@class); |
||||
|
||||
foreach (var method in @class.Methods) |
||||
{ |
||||
foreach (var pass in Passes.Passes) |
||||
pass.ProcessMethod(method); |
||||
} |
||||
|
||||
foreach (var field in @class.Fields) |
||||
{ |
||||
foreach (var pass in Passes.Passes) |
||||
pass.ProcessField(field); |
||||
|
||||
TransformDeclaration(field); |
||||
} |
||||
} |
||||
|
||||
void TransformFunction(Function function) |
||||
{ |
||||
foreach (var pass in Passes.Passes) |
||||
pass.ProcessFunction(function); |
||||
|
||||
TransformDeclaration(function); |
||||
|
||||
foreach (var param in function.Parameters) |
||||
TransformDeclaration(param); |
||||
} |
||||
|
||||
void TransformEnum(Enumeration @enum) |
||||
{ |
||||
TransformDeclaration(@enum); |
||||
|
||||
foreach (var item in @enum.Items) |
||||
{ |
||||
foreach (var pass in Passes.Passes) |
||||
pass.ProcessEnumItem(item); |
||||
} |
||||
|
||||
CheckIsFlagsEnum(@enum); |
||||
|
||||
// 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; |
||||
} |
||||
} |
||||
|
||||
private static void CheckIsFlagsEnum(Enumeration @enum) |
||||
{ |
||||
// 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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,187 @@
@@ -0,0 +1,187 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace Cxxi.Passes |
||||
{ |
||||
public class Preprocess : TranslationUnitPass |
||||
{ |
||||
private int uniqueName; |
||||
private TypeRefsVisitor typeRefs; |
||||
|
||||
public Preprocess() |
||||
{ |
||||
typeRefs = new TypeRefsVisitor(); |
||||
} |
||||
|
||||
public void ProcessLibrary(Library Library) |
||||
{ |
||||
if (string.IsNullOrEmpty(Library.Name)) |
||||
Library.Name = ""; |
||||
|
||||
// Process everything in the global namespace for now.
|
||||
foreach (var unit in Library.TranslationUnits) |
||||
{ |
||||
if (unit.ExplicityIgnored) |
||||
continue; |
||||
|
||||
if (unit.IsSystemHeader) |
||||
continue; |
||||
|
||||
typeRefs = new TypeRefsVisitor(); |
||||
ProcessNamespace(unit); |
||||
unit.ForwardReferences = typeRefs.ForwardReferences.ToList(); |
||||
} |
||||
} |
||||
|
||||
private void ProcessNamespace(Namespace @namespace) |
||||
{ |
||||
ProcessDeclarations(@namespace.Enums); |
||||
ProcessFunctions(@namespace.Functions); |
||||
ProcessClasses(@namespace.Classes); |
||||
ProcessTypedefs(@namespace, @namespace.Typedefs); |
||||
|
||||
foreach (var inner in @namespace.Namespaces) |
||||
ProcessNamespace(inner); |
||||
} |
||||
|
||||
public override bool ProcessDeclaration(Declaration decl) |
||||
{ |
||||
decl.Visit(typeRefs); |
||||
|
||||
// Generate a new name if the decl still does not have a name
|
||||
if (string.IsNullOrWhiteSpace(decl.Name)) |
||||
decl.Name = string.Format("_{0}", uniqueName++); |
||||
|
||||
StringHelpers.CleanupText(ref decl.DebugText); |
||||
return true; |
||||
} |
||||
|
||||
private void ProcessDeclarations<T>(IEnumerable<T> decls) where T : Declaration |
||||
{ |
||||
foreach (T decl in decls) |
||||
ProcessDeclaration(decl); |
||||
} |
||||
|
||||
private void ProcessClasses(List<Class> classes) |
||||
{ |
||||
ProcessDeclarations(classes); |
||||
|
||||
foreach (var @class in classes) |
||||
{ |
||||
ProcessFields(@class.Fields); |
||||
ProcessMethods(@class.Methods); |
||||
} |
||||
} |
||||
|
||||
private void ProcessFields(List<Field> fields) |
||||
{ |
||||
ProcessDeclarations(fields); |
||||
|
||||
foreach (var field in fields) |
||||
{ |
||||
var type = field.Type; |
||||
if (type == null || !IsTypeComplete(type) || IsTypeIgnored(type)) |
||||
{ |
||||
field.ExplicityIgnored = true; |
||||
Console.WriteLine( |
||||
"Field '{0}' was ignored due to unknown / ignored type", |
||||
field.Name); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public override bool ProcessFunction(Function function) |
||||
{ |
||||
var ret = function.ReturnType; |
||||
|
||||
if (ret == null || !IsTypeComplete(ret) || IsTypeIgnored(ret)) |
||||
{ |
||||
function.ExplicityIgnored = true; |
||||
Console.WriteLine( |
||||
"Function '{0}' was ignored due to unknown / ignored return decl", |
||||
function.Name); |
||||
} |
||||
|
||||
foreach (var param in function.Parameters) |
||||
{ |
||||
if (param == null || !IsDeclComplete(param) || IsDeclIgnored(param)) |
||||
{ |
||||
function.ExplicityIgnored = true; |
||||
Console.WriteLine( |
||||
"Function '{0}' was ignored due to unknown / ignored param", |
||||
function.Name); |
||||
} |
||||
|
||||
ProcessDeclaration(param); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private static bool IsTypeComplete(Type type) |
||||
{ |
||||
var checker = new TypeCompletionChecker(); |
||||
return type.Visit(checker); |
||||
} |
||||
|
||||
private static bool IsDeclComplete(Declaration decl) |
||||
{ |
||||
var checker = new TypeCompletionChecker(); |
||||
return decl.Visit(checker); |
||||
} |
||||
|
||||
private static bool IsTypeIgnored(Type type) |
||||
{ |
||||
var checker = new TypeIgnoreChecker(); |
||||
return type.Visit(checker); |
||||
} |
||||
|
||||
private static bool IsDeclIgnored(Declaration decl) |
||||
{ |
||||
var checker = new TypeIgnoreChecker(); |
||||
return decl.Visit(checker); |
||||
} |
||||
|
||||
public override bool ProcessMethod(Method method) |
||||
{ |
||||
return ProcessFunction(method); |
||||
} |
||||
|
||||
private void ProcessMethods(List<Method> methods) |
||||
{ |
||||
ProcessDeclarations(methods); |
||||
|
||||
foreach (var method in methods) |
||||
ProcessFunction(method); |
||||
} |
||||
|
||||
private void ProcessTypedefs(Namespace @namespace, List<TypedefDecl> typedefs) |
||||
{ |
||||
ProcessDeclarations(typedefs); |
||||
|
||||
foreach (var typedef in typedefs) |
||||
{ |
||||
var @class = @namespace.FindClass(typedef.Name); |
||||
|
||||
// Clang will walk the typedef'd tag decl and the typedef decl,
|
||||
// so we ignore the class and process just the typedef.
|
||||
|
||||
if (@class != null) |
||||
typedef.ExplicityIgnored = true; |
||||
|
||||
if (typedef.Type == null) |
||||
typedef.ExplicityIgnored = true; |
||||
} |
||||
} |
||||
|
||||
private void ProcessFunctions(List<Function> functions) |
||||
{ |
||||
ProcessDeclarations(functions); |
||||
|
||||
foreach (var function in functions) |
||||
ProcessFunction(function); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
namespace Cxxi.Types.Std |
||||
{ |
||||
[TypeMap("std::string")] |
||||
[TypeMap("std::wstring")] |
||||
public class String : TypeMap |
||||
{ |
||||
public override string Signature() |
||||
{ |
||||
return "System::String^"; |
||||
} |
||||
|
||||
public override string MarshalToNative(MarshalContext ctx) |
||||
{ |
||||
return string.Format("marshalString<E_UTF8>({0})", ctx.Parameter.Name); |
||||
} |
||||
|
||||
public override string MarshalFromNative(MarshalContext ctx) |
||||
{ |
||||
return string.Format("marshalString<E_UTF8>({0})", ctx.ReturnVarName); |
||||
} |
||||
} |
||||
|
||||
[TypeMap("std::vector")] |
||||
public class Vector : TypeMap |
||||
{ |
||||
public override string Signature() |
||||
{ |
||||
var type = Type as TemplateSpecializationType; |
||||
var typeName = type.Arguments[0].Type.ToString(); |
||||
return string.Format("System::Collections::Generic::List<{0}>^", typeName); |
||||
} |
||||
|
||||
public override string MarshalToNative(MarshalContext ctx) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public override string MarshalFromNative(MarshalContext ctx) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
[TypeMap("std::map")] |
||||
public class Map : TypeMap |
||||
{ |
||||
public override string Signature() |
||||
{ |
||||
var type = Type as TemplateSpecializationType; |
||||
return string.Format("System::Collections::Generic::Dictionary<{0}, {1}>^", |
||||
type.Arguments[0].Type, |
||||
type.Arguments[1].Type); |
||||
} |
||||
|
||||
public override string MarshalToNative(MarshalContext ctx) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public override string MarshalFromNative(MarshalContext ctx) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
[TypeMap("std::shared_ptr")] |
||||
public class SharedPtr : TypeMap |
||||
{ |
||||
public override string Signature() |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public override string MarshalToNative(MarshalContext ctx) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public override string MarshalFromNative(MarshalContext ctx) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
|
||||
namespace Cxxi.Types |
||||
{ |
||||
public class MarshalContext |
||||
{ |
||||
public string ArgName { get; set; } |
||||
public string ReturnVarName { get; set; } |
||||
public Parameter Parameter { get; set; } |
||||
} |
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] |
||||
public class TypeMapAttribute : Attribute |
||||
{ |
||||
public string Type { get; private set; } |
||||
|
||||
public TypeMapAttribute(string type) |
||||
{ |
||||
Type = type; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// This is similar to the SWIG type map concept, and allows some
|
||||
/// freedom and customization when translating between the source and
|
||||
/// target language types.
|
||||
/// </summary>
|
||||
public abstract class TypeMap |
||||
{ |
||||
public Type Type { get; set; } |
||||
public Declaration Declaration { get; set; } |
||||
|
||||
public virtual bool IsValueType |
||||
{ |
||||
get { return false; } |
||||
} |
||||
|
||||
public abstract string Signature(); |
||||
public abstract string MarshalToNative(MarshalContext ctx); |
||||
public abstract string MarshalFromNative(MarshalContext ctx); |
||||
} |
||||
|
||||
public class TypeDatabase |
||||
{ |
||||
public IDictionary<string, System.Type> TypeMaps { get; set; } |
||||
|
||||
public TypeDatabase() |
||||
{ |
||||
TypeMaps = new Dictionary<string, System.Type>(); |
||||
} |
||||
|
||||
public void SetupTypeMaps() |
||||
{ |
||||
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); |
||||
|
||||
foreach (var assembly in loadedAssemblies) |
||||
{ |
||||
var types = assembly.FindDerivedTypes(typeof(TypeMap)); |
||||
|
||||
foreach (var typeMap in types) |
||||
{ |
||||
var attrs = typeMap.GetCustomAttributes<TypeMapAttribute>(); |
||||
if (attrs == null) continue; |
||||
|
||||
foreach (var attr in attrs) |
||||
{ |
||||
Console.WriteLine("Found typemap: {0}", attr.Type); |
||||
TypeMaps[attr.Type] = typeMap; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public bool FindTypeMap(string name, out TypeMap typeMap) |
||||
{ |
||||
System.Type type; |
||||
TypeMaps.TryGetValue(name, out type); |
||||
|
||||
if (type == null) |
||||
{ |
||||
typeMap = null; |
||||
return false; |
||||
} |
||||
|
||||
typeMap = (TypeMap)Activator.CreateInstance(type); |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,276 @@
@@ -0,0 +1,276 @@
|
||||
using System.Collections.Generic; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
/// <summary>
|
||||
/// Base class for type checkers.
|
||||
/// You can override the methods to customize the behaviour, by default
|
||||
/// this will visit all the nodes in a default way that should be useful
|
||||
/// for a lot of applications.
|
||||
/// </summary>
|
||||
public abstract class TypeChecker : ITypeVisitor<bool>, IDeclVisitor<bool> |
||||
{ |
||||
public virtual bool VisitTagType(TagType tag, TypeQualifiers quals) |
||||
{ |
||||
return tag.Declaration.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitArrayType(ArrayType array, TypeQualifiers quals) |
||||
{ |
||||
return array.Type.Visit(this, quals); |
||||
} |
||||
|
||||
public virtual bool VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||
{ |
||||
if (function.ReturnType != null) |
||||
function.ReturnType.Visit(this); |
||||
|
||||
foreach (var param in function.Arguments) |
||||
param.Visit(this); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public virtual bool VisitPointerType(PointerType pointer, TypeQualifiers quals) |
||||
{ |
||||
if (pointer.Pointee == null) |
||||
return false; |
||||
return pointer.Pointee.Visit(this, quals); |
||||
} |
||||
|
||||
public virtual bool VisitMemberPointerType(MemberPointerType member, TypeQualifiers quals) |
||||
{ |
||||
return member.Pointee.Visit(this, quals); |
||||
} |
||||
|
||||
public virtual bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
public virtual bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) |
||||
{ |
||||
return typedef.Declaration.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) |
||||
{ |
||||
return template.Template.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitDeclaration(Declaration decl, TypeQualifiers quals) |
||||
{ |
||||
return VisitDeclaration(decl); |
||||
} |
||||
|
||||
public virtual bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
public virtual bool VisitClassDecl(Class @class) |
||||
{ |
||||
return VisitDeclaration(@class); |
||||
} |
||||
|
||||
public virtual bool VisitFieldDecl(Field field) |
||||
{ |
||||
return field.Type.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitFunctionDecl(Function function) |
||||
{ |
||||
if (function.ReturnType == null) |
||||
return false; |
||||
|
||||
function.ReturnType.Visit(this); |
||||
|
||||
foreach (var param in function.Parameters) |
||||
param.Visit(this); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public virtual bool VisitMethodDecl(Method method) |
||||
{ |
||||
return VisitFunctionDecl(method); |
||||
} |
||||
|
||||
public virtual bool VisitParameterDecl(Parameter parameter) |
||||
{ |
||||
return parameter.Type.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitTypedefDecl(TypedefDecl typedef) |
||||
{ |
||||
if (typedef.Type == null) |
||||
return false; |
||||
return typedef.Type.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
return VisitDeclaration(@enum); |
||||
} |
||||
|
||||
public virtual bool VisitClassTemplateDecl(ClassTemplate template) |
||||
{ |
||||
return template.TemplatedClass.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitFunctionTemplateDecl(FunctionTemplate template) |
||||
{ |
||||
return template.TemplatedFunction.Visit(this); |
||||
} |
||||
|
||||
public virtual bool VisitMacroDefinition(MacroDefinition macro) |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// This type checker is used to check if a type is complete.
|
||||
/// </summary>
|
||||
public class TypeCompletionChecker : TypeChecker |
||||
{ |
||||
public override bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
return !decl.IsIncomplete; |
||||
} |
||||
|
||||
public override bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||
{ |
||||
if (!function.ReturnType.Visit(this)) |
||||
return false; |
||||
|
||||
foreach (var arg in function.Arguments) |
||||
{ |
||||
if (!arg.Type.Visit(this)) |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitFunctionDecl(Function function) |
||||
{ |
||||
if (!function.ReturnType.Visit(this)) |
||||
return false; |
||||
|
||||
foreach (var param in function.Parameters) |
||||
{ |
||||
if (!param.Visit(this)) |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// This type checker is used to check if a type is ignored.
|
||||
/// </summary>
|
||||
public class TypeIgnoreChecker : TypeChecker |
||||
{ |
||||
public override bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
return decl.Ignore; |
||||
} |
||||
|
||||
public override bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||
{ |
||||
if (!function.ReturnType.Visit(this)) |
||||
return false; |
||||
|
||||
foreach (var arg in function.Arguments) |
||||
{ |
||||
if (!arg.Type.Visit(this)) |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitFunctionDecl(Function function) |
||||
{ |
||||
if (!function.ReturnType.Visit(this)) |
||||
return false; |
||||
|
||||
foreach (var param in function.Parameters) |
||||
{ |
||||
if (!param.Visit(this)) |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// This is used to get the declarations that each file needs to forward
|
||||
/// reference or include from other header files. Since in C++ everything
|
||||
/// that is referenced needs to have been declared previously, it can happen
|
||||
/// that a file needs to be reference something that has not been declared
|
||||
/// yet. In that case, we need to declare it before referencing it.
|
||||
/// </summary>
|
||||
class TypeRefsVisitor : TypeChecker |
||||
{ |
||||
public ISet<Declaration> ForwardReferences; |
||||
|
||||
public void Collect(Declaration declaration) |
||||
{ |
||||
if (declaration.Namespace.TranslationUnit.IsSystemHeader) |
||||
return; |
||||
|
||||
ForwardReferences.Add(declaration); |
||||
} |
||||
|
||||
public TypeRefsVisitor() |
||||
{ |
||||
ForwardReferences = new HashSet<Declaration>(); |
||||
} |
||||
|
||||
public override bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
// Built-in types should not need forward references.
|
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitClassDecl(Class @class) |
||||
{ |
||||
Collect(@class); |
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitParameterDecl(Parameter parameter) |
||||
{ |
||||
if (parameter.Type == null) |
||||
return false; |
||||
|
||||
return parameter.Type.Visit(this); |
||||
} |
||||
|
||||
public override bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
Collect(@enum); |
||||
return @enum.Type.Visit(this, new TypeQualifiers()); |
||||
} |
||||
|
||||
public override bool VisitMacroDefinition(MacroDefinition macro) |
||||
{ |
||||
// Macros are not relevant for forward references.
|
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
@ -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,176 @@
@@ -0,0 +1,176 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
namespace Cxxi |
||||
{ |
||||
public static class IntHelpers |
||||
{ |
||||
public static bool IsPowerOfTwo(this long x) |
||||
{ |
||||
return (x != 0) && ((x & (x - 1)) == 0); |
||||
} |
||||
} |
||||
|
||||
public static class PrimitiveTypeExtensions |
||||
{ |
||||
public static System.Type ConvertToType(this PrimitiveType primitive) |
||||
{ |
||||
switch (primitive) |
||||
{ |
||||
case PrimitiveType.Bool: return typeof(bool); |
||||
case PrimitiveType.Void: return typeof(void); |
||||
case PrimitiveType.WideChar: return typeof(char); |
||||
case PrimitiveType.Int8: return typeof(sbyte); |
||||
case PrimitiveType.UInt8: return typeof(byte); |
||||
case PrimitiveType.Int16: return typeof(short); |
||||
case PrimitiveType.UInt16: return typeof(ushort); |
||||
case PrimitiveType.Int32: return typeof(int); |
||||
case PrimitiveType.UInt32: return typeof(uint); |
||||
case PrimitiveType.Int64: return typeof(long); |
||||
case PrimitiveType.UInt64: return typeof(ulong); |
||||
case PrimitiveType.Float: return typeof(float); |
||||
case PrimitiveType.Double: return typeof(double); |
||||
} |
||||
|
||||
return typeof(int); |
||||
} |
||||
} |
||||
|
||||
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
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Word wraps the given text to fit within the specified width.
|
||||
/// </summary>
|
||||
/// <param name="text">Text to be word wrapped</param>
|
||||
/// <param name="width">Width, in characters, to which the text
|
||||
/// should be word wrapped</param>
|
||||
/// <returns>The modified text</returns>
|
||||
public static List<string> WordWrapLines(string text, int width) |
||||
{ |
||||
int pos, next; |
||||
var lines = new List<string>(); |
||||
|
||||
// Lucidity check
|
||||
if (width < 1) |
||||
{ |
||||
lines.Add(text); |
||||
return lines; |
||||
} |
||||
|
||||
// Parse each line of text
|
||||
for (pos = 0; pos < text.Length; pos = next) |
||||
{ |
||||
// Find end of line
|
||||
int eol = text.IndexOf(Environment.NewLine, pos, |
||||
System.StringComparison.Ordinal); |
||||
if (eol == -1) |
||||
next = eol = text.Length; |
||||
else |
||||
next = eol + Environment.NewLine.Length; |
||||
|
||||
// Copy this line of text, breaking into smaller lines as needed
|
||||
if (eol > pos) |
||||
{ |
||||
do |
||||
{ |
||||
int len = eol - pos; |
||||
if (len > width) |
||||
len = BreakLine(text, pos, width); |
||||
lines.Add(text.Substring(pos, len)); |
||||
|
||||
// Trim whitespace following break
|
||||
pos += len; |
||||
while (pos < eol && Char.IsWhiteSpace(text[pos])) |
||||
pos++; |
||||
} while (eol > pos); |
||||
} |
||||
else lines.Add(string.Empty); // Empty line
|
||||
} |
||||
return lines; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Locates position to break the given line so as to avoid
|
||||
/// breaking words.
|
||||
/// </summary>
|
||||
/// <param name="text">String that contains line of text</param>
|
||||
/// <param name="pos">Index where line of text starts</param>
|
||||
/// <param name="max">Maximum line length</param>
|
||||
/// <returns>The modified line length</returns>
|
||||
private static int BreakLine(string text, int pos, int max) |
||||
{ |
||||
// Find last whitespace in line
|
||||
int i = max; |
||||
while (i >= 0 && !Char.IsWhiteSpace(text[pos + i])) |
||||
i--; |
||||
|
||||
// If no whitespace found, break at maximum length
|
||||
if (i < 0) |
||||
return max; |
||||
|
||||
// Find start of whitespace
|
||||
while (i >= 0 && Char.IsWhiteSpace(text[pos + i])) |
||||
i--; |
||||
|
||||
// Return length of text before whitespace
|
||||
return i + 1; |
||||
} |
||||
|
||||
public static 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", ""); |
||||
} |
||||
} |
||||
|
||||
static class AssemblyHelpers |
||||
{ |
||||
public static IEnumerable<System.Type> FindDerivedTypes(this Assembly assembly, |
||||
System.Type baseType) |
||||
{ |
||||
return assembly.GetTypes().Where(baseType.IsAssignableFrom); |
||||
} |
||||
} |
||||
|
||||
static class Log |
||||
{ |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0"?> |
||||
<configuration> |
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration> |
||||
Loading…
Reference in new issue