2009-08-12 10:12:16 +00:00
#region - - - License - - -
2009-02-22 10:43:35 +00:00
/ * Copyright ( c ) 2006 , 2007 Stefanos Apostolopoulos
* See license . txt for license info
* /
#endregion
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
2009-08-17 12:28:22 +00:00
using System.IO ;
2009-10-27 22:37:05 +00:00
using System.Linq ;
2009-02-22 10:43:35 +00:00
using System.Text.RegularExpressions ;
2009-05-29 15:57:01 +00:00
using System.Xml.XPath ;
2009-08-17 12:28:22 +00:00
using Bind.Structures ;
2009-08-21 20:28:14 +00:00
using Delegate = Bind . Structures . Delegate ;
using Enum = Bind . Structures . Enum ;
using Type = Bind . Structures . Type ;
2009-02-22 10:43:35 +00:00
namespace Bind.GL2
{
class Generator : IBind
{
#region - - - Fields - - -
2009-03-08 18:08:35 +00:00
protected static string glTypemap = "GL2/gl.tm" ;
2009-02-22 10:43:35 +00:00
protected static string csTypemap = "csharp.tm" ;
2009-03-08 18:08:35 +00:00
protected static string enumSpec = "GL2/enum.spec" ;
protected static string enumSpecExt = "GL2/enumext.spec" ;
protected static string glSpec = "GL2/gl.spec" ;
2009-02-22 10:43:35 +00:00
protected static string glSpecExt = "" ;
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
protected static string importsFile = "GLCore.cs" ;
2009-02-28 19:29:34 +00:00
protected static string delegatesFile = "GLDelegates.cs" ;
protected static string enumsFile = "GLEnums.cs" ;
protected static string wrappersFile = "GL.cs" ;
2009-02-22 10:43:35 +00:00
2009-06-30 08:39:35 +00:00
protected static string functionOverridesFile = "GL2/gloverrides.xml" ;
2009-05-29 15:57:01 +00:00
2009-02-22 10:43:35 +00:00
protected static string loadAllFuncName = "LoadAll" ;
protected static Regex enumToDotNet = new Regex ( "_[a-z|A-Z]?" , RegexOptions . Compiled ) ;
2009-03-21 21:44:07 +00:00
protected static readonly char [ ] numbers = "0123456789" . ToCharArray ( ) ;
//protected static readonly Dictionary<string, string> doc_replacements;
2009-02-22 10:43:35 +00:00
#endregion
#region - - - Constructors - - -
public Generator ( )
{
if ( Settings . Compatibility = = Settings . Legacy . Tao )
{
Settings . OutputNamespace = "Tao.OpenGl" ;
Settings . OutputClass = "Gl" ;
}
else
{
// Defaults
}
}
#endregion
#region public void Process ( )
public virtual void Process ( )
{
// Matches functions that cannot have their trailing 'v' trimmed for CLS-Compliance reasons.
// Built through trial and error :)
2009-04-12 18:23:01 +00:00
//Function.endingsAddV =
// new Regex(@"(Coord1|Attrib(I?)1(u?)|Stream1|Uniform2(u?)|(Point|Convolution|Transform|Sprite|List|Combiner|Tex)Parameter|Fog(Coord)?.*|VertexWeight|(Fragment)?Light(Model)?|Material|ReplacementCodeu?b?|Tex(Gen|Env)|Indexu?|TextureParameter.v)",
// RegexOptions.Compiled);
2009-02-22 10:43:35 +00:00
2009-08-21 20:28:14 +00:00
Type . Initialize ( glTypemap , csTypemap ) ;
Enum . Initialize ( enumSpec , enumSpecExt ) ;
Enum . GLEnums . Translate ( new XPathDocument ( Path . Combine ( Settings . InputPath , functionOverridesFile ) ) ) ;
Function . Initialize ( ) ;
Delegate . Initialize ( glSpec , glSpecExt ) ;
2009-02-22 10:43:35 +00:00
2009-08-25 15:59:57 +00:00
WriteBindings (
2009-08-21 20:28:14 +00:00
Delegate . Delegates ,
Function . Wrappers ,
Enum . GLEnums ) ;
2009-02-22 10:43:35 +00:00
}
#endregion
#region private void Translate ( )
#if false
protected virtual void Translate ( )
{
Bind . Structures . Enum . GLEnums . Translate ( ) ;
}
#endif
#endregion
#region ISpecReader Members
#region public virtual DelegateCollection ReadDelegates ( StreamReader specFile )
public virtual DelegateCollection ReadDelegates ( StreamReader specFile )
{
Console . WriteLine ( "Reading function specs." ) ;
DelegateCollection delegates = new DelegateCollection ( ) ;
2009-06-30 08:39:35 +00:00
XPathDocument function_overrides = new XPathDocument ( Path . Combine ( Settings . InputPath , functionOverridesFile ) ) ;
2009-02-22 10:43:35 +00:00
do
{
string line = NextValidLine ( specFile ) ;
if ( String . IsNullOrEmpty ( line ) )
break ;
while ( line . Contains ( "(" ) & & ! specFile . EndOfStream )
{
// Get next OpenGL function
2009-08-21 20:28:14 +00:00
Delegate d = new Delegate ( ) ;
2009-02-22 10:43:35 +00:00
// Get function name:
d . Name = line . Split ( Utilities . Separators , StringSplitOptions . RemoveEmptyEntries ) [ 0 ] ;
do
{
// Get function parameters and return value
line = specFile . ReadLine ( ) ;
List < string > words = new List < string > (
line . Replace ( '\t' , ' ' ) . Split ( Utilities . Separators , StringSplitOptions . RemoveEmptyEntries )
) ;
if ( words . Count = = 0 )
break ;
// Identify line:
switch ( words [ 0 ] )
{
case "return" : // Line denotes return value
d . ReturnType . CurrentType = words [ 1 ] ;
break ;
case "param" : // Line denotes parameter
Parameter p = new Parameter ( ) ;
p . Name = Utilities . Keywords . Contains ( words [ 1 ] ) ? "@" + words [ 1 ] : words [ 1 ] ;
p . CurrentType = words [ 2 ] ;
2009-07-15 22:33:26 +00:00
p . Pointer + = words [ 4 ] . Contains ( "array" ) ? 1 : 0 ;
p . Pointer + = words [ 4 ] . Contains ( "reference" ) ? 1 : 0 ;
if ( p . Pointer ! = 0 & & words . Count > 5 & & words [ 5 ] . Contains ( "[1]" ) )
2009-04-15 13:14:41 +00:00
p . ElementCount = 1 ;
2009-07-15 22:33:26 +00:00
p . Flow = words [ 3 ] = = "in" ? FlowDirection . In : FlowDirection . Out ;
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
d . Parameters . Add ( p ) ;
break ;
2009-02-28 19:29:34 +00:00
// GetTexParameterIivEXT and GetTexParameterIuivEXT define two(!) versions (why?)
case "version" : // Line denotes function version (i.e. 1.0, 1.2, 1.5)
d . Version = words [ 1 ] ;
break ;
2009-02-22 10:43:35 +00:00
case "category" :
d . Category = words [ 1 ] ;
break ;
}
}
while ( ! specFile . EndOfStream ) ;
2009-05-29 15:57:01 +00:00
d . Translate ( function_overrides ) ;
2009-02-22 10:43:35 +00:00
delegates . Add ( d ) ;
}
}
while ( ! specFile . EndOfStream ) ;
return delegates ;
}
#endregion
#region public virtual EnumCollection ReadEnums ( StreamReader specFile )
public virtual EnumCollection ReadEnums ( StreamReader specFile )
{
Trace . WriteLine ( "Reading opengl enumerant specs." ) ;
Trace . Indent ( ) ;
EnumCollection enums = new EnumCollection ( ) ;
// complete_enum contains all opengl enumerants.
2009-08-21 20:28:14 +00:00
Enum complete_enum = new Enum ( ) ;
2009-02-22 10:43:35 +00:00
complete_enum . Name = Settings . CompleteEnumName ;
do
{
string line = NextValidLine ( specFile ) ;
if ( String . IsNullOrEmpty ( line ) )
break ;
line = line . Replace ( '\t' , ' ' ) ;
// We just encountered the start of a new enumerant:
while ( ! String . IsNullOrEmpty ( line ) & & line . Contains ( "enum" ) )
{
string [ ] words = line . Split ( Utilities . Separators , StringSplitOptions . RemoveEmptyEntries ) ;
if ( words . Length = = 0 )
continue ;
// Declare a new enumerant
2009-08-21 20:28:14 +00:00
Enum e = new Enum ( ) ;
2009-02-22 10:43:35 +00:00
e . Name = Char . IsDigit ( words [ 0 ] [ 0 ] ) ? Settings . ConstantPrefix + words [ 0 ] : words [ 0 ] ;
// And fill in the values for this enumerant
do
{
line = NextValidLine ( specFile ) ;
if ( String . IsNullOrEmpty ( line ) | | line . StartsWith ( "#" ) )
continue ;
if ( line . Contains ( "enum:" ) | | specFile . EndOfStream )
break ;
line = line . Replace ( '\t' , ' ' ) ;
words = line . Split ( Utilities . Separators , StringSplitOptions . RemoveEmptyEntries ) ;
if ( words . Length = = 0 )
continue ;
// If we reach this point, we have found a new value for the current enumerant
Constant c = new Constant ( ) ;
if ( line . Contains ( "=" ) )
{
// Trim the name's prefix, but only if not in Tao compat mode.
if ( Settings . Compatibility = = Settings . Legacy . Tao )
{
}
else
{
if ( words [ 0 ] . StartsWith ( Settings . ConstantPrefix ) )
words [ 0 ] = words [ 0 ] . Substring ( Settings . ConstantPrefix . Length ) ;
if ( Char . IsDigit ( words [ 0 ] [ 0 ] ) )
words [ 0 ] = Settings . ConstantPrefix + words [ 0 ] ;
}
c . Name = words [ 0 ] ;
c . Value = words [ 2 ] ;
}
else if ( words [ 0 ] = = "use" )
{
// Trim the prefix.
if ( words [ 2 ] . StartsWith ( Settings . ConstantPrefix ) )
words [ 2 ] = words [ 2 ] . Substring ( Settings . ConstantPrefix . Length ) ;
// If the remaining string starts with a digit, we were wrong above.
// Re-add the "GL_"
if ( Char . IsDigit ( words [ 2 ] [ 0 ] ) )
words [ 2 ] = Settings . ConstantPrefix + words [ 2 ] ;
c . Name = words [ 2 ] ;
c . Reference = words [ 1 ] ;
c . Value = words [ 2 ] ;
}
2009-09-07 17:49:06 +00:00
else
{
// Typical cause is hand-editing the specs and forgetting to add an '=' sign.
throw new InvalidOperationException ( String . Format (
"[Error] Invalid constant definition: \"{0}\"" , line ) ) ;
}
2009-02-22 10:43:35 +00:00
//if (!String.IsNullOrEmpty(c.Name) && !e.Members.Contains.Contains(c))
//SpecTranslator.Merge(e.Members, c);
if ( ! e . ConstantCollection . ContainsKey ( c . Name ) )
e . ConstantCollection . Add ( c . Name , c ) ;
else
Trace . WriteLine ( String . Format (
"Spec error: Constant {0} defined twice in enum {1}, discarding last definition." ,
c . Name , e . Name ) ) ;
// Insert the current constant in the list of all constants.
//SpecTranslator.Merge(complete_enum.Members, c);
complete_enum = Utilities . Merge ( complete_enum , c ) ;
}
while ( ! specFile . EndOfStream ) ;
// At this point, the complete value list for the current enumerant has been read, so add this
// enumerant to the list.
//e.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "public enum " + e.Name));
//e.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "public enum " + e.Name));
// (disabled) Hack - discard Boolean enum, it fsucks up the fragile translation code ahead.
//if (!e.Name.Contains("Bool"))
//Utilities.Merge(enums, e);
//e.Translate();
if ( ! enums . ContainsKey ( e . Name ) )
enums . Add ( e . Name , e ) ;
else
{
// The enum already exists, merge constants.
foreach ( Constant t in e . ConstantCollection . Values )
Utilities . Merge ( enums [ e . Name ] , t ) ;
}
}
}
while ( ! specFile . EndOfStream ) ;
enums . Add ( complete_enum . Name , complete_enum ) ;
Trace . Unindent ( ) ;
return enums ;
}
#endregion
#region public virtual Dictionary < string , string > ReadTypeMap ( StreamReader specFile )
public virtual Dictionary < string , string > ReadTypeMap ( StreamReader specFile )
{
Console . WriteLine ( "Reading opengl types." ) ;
Dictionary < string , string > GLTypes = new Dictionary < string , string > ( ) ;
2009-08-11 15:33:17 +00:00
if ( specFile = = null )
return GLTypes ;
2009-02-22 10:43:35 +00:00
do
{
string line = specFile . ReadLine ( ) ;
if ( String . IsNullOrEmpty ( line ) | | line . StartsWith ( "#" ) )
continue ;
string [ ] words = line . Split ( " ,*\t" . ToCharArray ( ) , StringSplitOptions . RemoveEmptyEntries ) ;
if ( words [ 0 ] . ToLower ( ) = = "void" )
{
// Special case for "void" -> "". We make it "void" -> "void"
GLTypes . Add ( words [ 0 ] , "void" ) ;
}
else if ( words [ 0 ] = = "VoidPointer" | | words [ 0 ] = = "ConstVoidPointer" )
{
// "(Const)VoidPointer" -> "void*"
GLTypes . Add ( words [ 0 ] , "void*" ) ;
}
2009-06-29 18:32:51 +00:00
else if ( words [ 0 ] = = "CharPointer" | | words [ 0 ] = = "charPointerARB" )
2009-02-22 10:43:35 +00:00
{
2009-06-29 18:32:51 +00:00
// The typematching logic cannot handle pointers to pointers, e.g. CharPointer* -> char** -> string* -> string[].
// Hence we give it a push.
// Note: When both CurrentType == "String" and Pointer == true, the typematching is hardcoded to use
2009-10-27 22:37:05 +00:00
// String[] or StringBuilder[].
GLTypes . Add ( words [ 0 ] , "String" ) ;
2009-02-22 10:43:35 +00:00
}
2009-06-29 18:32:51 +00:00
/ * else if ( words [ 0 ] . Contains ( "Pointer" ) )
2009-02-22 10:43:35 +00:00
{
GLTypes . Add ( words [ 0 ] , words [ 1 ] . Replace ( "Pointer" , "*" ) ) ;
} * /
else if ( words [ 1 ] . Contains ( "GLvoid" ) )
{
GLTypes . Add ( words [ 0 ] , "void" ) ;
}
else
{
GLTypes . Add ( words [ 0 ] , words [ 1 ] ) ;
}
}
while ( ! specFile . EndOfStream ) ;
return GLTypes ;
}
#endregion
#region public virtual Dictionary < string , string > ReadCSTypeMap ( StreamReader specFile )
public virtual Dictionary < string , string > ReadCSTypeMap ( StreamReader specFile )
{
Dictionary < string , string > CSTypes = new Dictionary < string , string > ( ) ;
Console . WriteLine ( "Reading C# types." ) ;
while ( ! specFile . EndOfStream )
{
string line = specFile . ReadLine ( ) ;
if ( String . IsNullOrEmpty ( line ) | | line . StartsWith ( "#" ) )
continue ;
string [ ] words = line . Split ( " ,\t" . ToCharArray ( ) , StringSplitOptions . RemoveEmptyEntries ) ;
if ( words . Length < 2 )
continue ;
if ( ( ( Settings . Compatibility & Settings . Legacy . NoBoolParameters ) ! = Settings . Legacy . None ) & & words [ 1 ] = = "bool" )
words [ 1 ] = "Int32" ;
CSTypes . Add ( words [ 0 ] , words [ 1 ] ) ;
}
return CSTypes ;
}
#endregion
#region private string NextValidLine ( StreamReader sr )
2009-08-21 20:28:14 +00:00
private string NextValidLine ( StreamReader sr )
2009-02-22 10:43:35 +00:00
{
string line ;
do
{
if ( sr . EndOfStream )
return null ;
line = sr . ReadLine ( ) . Trim ( ) ;
if ( String . IsNullOrEmpty ( line ) | |
line . StartsWith ( "#" ) | | // Disregard comments.
line . StartsWith ( "passthru" ) | | // Disregard passthru statements.
line . StartsWith ( "required-props:" ) | |
line . StartsWith ( "param:" ) | |
line . StartsWith ( "dlflags:" ) | |
line . StartsWith ( "glxflags:" ) | |
line . StartsWith ( "vectorequiv:" ) | |
//line.StartsWith("category:") ||
line . StartsWith ( "version:" ) | |
line . StartsWith ( "glxsingle:" ) | |
line . StartsWith ( "glxropcode:" ) | |
line . StartsWith ( "glxvendorpriv:" ) | |
line . StartsWith ( "glsflags:" ) | |
line . StartsWith ( "glsopcode:" ) | |
line . StartsWith ( "glsalias:" ) | |
line . StartsWith ( "wglflags:" ) | |
line . StartsWith ( "extension:" ) | |
line . StartsWith ( "alias:" ) | |
line . StartsWith ( "offset:" ) )
continue ;
return line ;
}
while ( true ) ;
}
#endregion
#endregion
#region ISpecWriter Members
#region void WriteBindings
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
public void WriteBindings ( DelegateCollection delegates , FunctionCollection functions , EnumCollection enums )
{
2009-03-08 18:08:35 +00:00
Console . WriteLine ( "Writing bindings to {0}" , Settings . OutputPath ) ;
2009-02-22 10:43:35 +00:00
if ( ! Directory . Exists ( Settings . OutputPath ) )
Directory . CreateDirectory ( Settings . OutputPath ) ;
2009-05-30 15:28:52 +00:00
string temp_enums_file = Path . GetTempFileName ( ) ;
string temp_delegates_file = Path . GetTempFileName ( ) ;
string temp_core_file = Path . GetTempFileName ( ) ;
string temp_wrappers_file = Path . GetTempFileName ( ) ;
2009-03-08 00:46:58 +00:00
// Enums
2009-05-30 15:28:52 +00:00
using ( BindStreamWriter sw = new BindStreamWriter ( temp_enums_file ) )
2009-02-22 10:43:35 +00:00
{
2009-03-08 18:08:35 +00:00
WriteLicense ( sw ) ;
2009-05-05 21:00:48 +00:00
sw . WriteLine ( "using System;" ) ;
sw . WriteLine ( ) ;
2009-02-22 10:43:35 +00:00
if ( ( Settings . Compatibility & Settings . Legacy . NestedEnums ) ! = Settings . Legacy . None )
{
sw . WriteLine ( "namespace {0}" , Settings . OutputNamespace ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
sw . WriteLine ( "static partial class {0}" , Settings . OutputClass ) ;
}
else
sw . WriteLine ( "namespace {0}" , Settings . EnumsOutput ) ;
sw . WriteLine ( "{" ) ;
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
sw . Indent ( ) ;
2009-08-21 20:28:14 +00:00
WriteEnums ( sw , Enum . GLEnums ) ;
2009-02-22 10:43:35 +00:00
sw . Unindent ( ) ;
if ( ( Settings . Compatibility & Settings . Legacy . NestedEnums ) ! = Settings . Legacy . None )
{
sw . WriteLine ( "}" ) ;
sw . Unindent ( ) ;
}
sw . WriteLine ( "}" ) ;
}
2009-03-08 00:46:58 +00:00
// Delegates
2009-05-30 15:28:52 +00:00
using ( BindStreamWriter sw = new BindStreamWriter ( temp_delegates_file ) )
2009-02-22 10:43:35 +00:00
{
2009-03-08 18:08:35 +00:00
WriteLicense ( sw ) ;
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "namespace {0}" , Settings . OutputNamespace ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
sw . WriteLine ( "using System;" ) ;
2009-10-27 22:37:05 +00:00
sw . WriteLine ( "using System.Text;" ) ;
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "using System.Runtime.InteropServices;" ) ;
sw . WriteLine ( "#pragma warning disable 0649" ) ;
2009-08-21 20:28:14 +00:00
WriteDelegates ( sw , Delegate . Delegates ) ;
2009-02-22 10:43:35 +00:00
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
}
2009-03-08 00:46:58 +00:00
// Core
2009-05-30 15:28:52 +00:00
using ( BindStreamWriter sw = new BindStreamWriter ( temp_core_file ) )
2009-02-22 10:43:35 +00:00
{
2009-03-08 18:08:35 +00:00
WriteLicense ( sw ) ;
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "namespace {0}" , Settings . OutputNamespace ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
//specWriter.WriteTypes(sw, Bind.Structures.Type.CSTypes);
sw . WriteLine ( "using System;" ) ;
2009-10-27 22:37:05 +00:00
sw . WriteLine ( "using System.Text;" ) ;
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "using System.Runtime.InteropServices;" ) ;
2009-02-28 19:29:34 +00:00
2009-08-21 20:28:14 +00:00
WriteImports ( sw , Delegate . Delegates ) ;
2009-02-22 10:43:35 +00:00
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
}
2009-03-08 00:46:58 +00:00
// Wrappers
2009-05-30 15:28:52 +00:00
using ( BindStreamWriter sw = new BindStreamWriter ( temp_wrappers_file ) )
2009-02-22 10:43:35 +00:00
{
2009-03-08 18:08:35 +00:00
WriteLicense ( sw ) ;
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "namespace {0}" , Settings . OutputNamespace ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
sw . WriteLine ( "using System;" ) ;
2009-10-27 22:37:05 +00:00
sw . WriteLine ( "using System.Text;" ) ;
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "using System.Runtime.InteropServices;" ) ;
2009-08-21 20:28:14 +00:00
WriteWrappers ( sw , Function . Wrappers , Type . CSTypes ) ;
2009-02-22 10:43:35 +00:00
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
}
2009-05-30 15:28:52 +00:00
2009-07-15 15:01:55 +00:00
string output_enums = Path . Combine ( Settings . OutputPath , enumsFile ) ;
string output_delegates = Path . Combine ( Settings . OutputPath , delegatesFile ) ;
string output_core = Path . Combine ( Settings . OutputPath , importsFile ) ;
string output_wrappers = Path . Combine ( Settings . OutputPath , wrappersFile ) ;
if ( File . Exists ( output_enums ) ) File . Delete ( output_enums ) ;
if ( File . Exists ( output_delegates ) ) File . Delete ( output_delegates ) ;
if ( File . Exists ( output_core ) ) File . Delete ( output_core ) ;
if ( File . Exists ( output_wrappers ) ) File . Delete ( output_wrappers ) ;
File . Move ( temp_enums_file , output_enums ) ;
File . Move ( temp_delegates_file , output_delegates ) ;
File . Move ( temp_core_file , output_core ) ;
File . Move ( temp_wrappers_file , output_wrappers ) ;
2009-02-22 10:43:35 +00:00
}
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
#endregion
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
#region void WriteDelegates
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
public virtual void WriteDelegates ( BindStreamWriter sw , DelegateCollection delegates )
{
Trace . WriteLine ( String . Format ( "Writing delegates to:\t{0}.{1}.{2}" , Settings . OutputNamespace , Settings . OutputClass , Settings . DelegatesClass ) ) ;
sw . WriteLine ( "#pragma warning disable 3019" ) ; // CLSCompliant attribute
sw . WriteLine ( "#pragma warning disable 1591" ) ; // Missing doc comments
sw . WriteLine ( ) ;
sw . WriteLine ( "partial class {0}" , Settings . OutputClass ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
sw . WriteLine ( "internal static partial class {0}" , Settings . DelegatesClass ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
2009-02-28 19:29:34 +00:00
2009-08-21 20:28:14 +00:00
foreach ( Delegate d in delegates . Values )
2009-02-22 10:43:35 +00:00
{
sw . WriteLine ( "[System.Security.SuppressUnmanagedCodeSecurity()]" ) ;
sw . WriteLine ( "internal {0};" , d . ToString ( ) ) ;
sw . WriteLine ( "internal {0}static {1} {2}{1};" , // = null
d . Unsafe ? "unsafe " : "" ,
d . Name ,
Settings . FunctionPrefix ) ;
}
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
}
#endregion
#region void WriteImports
public virtual void WriteImports ( BindStreamWriter sw , DelegateCollection delegates )
{
Trace . WriteLine ( String . Format ( "Writing imports to:\t{0}.{1}.{2}" , Settings . OutputNamespace , Settings . OutputClass , Settings . ImportsClass ) ) ;
sw . WriteLine ( "#pragma warning disable 3019" ) ; // CLSCompliant attribute
sw . WriteLine ( "#pragma warning disable 1591" ) ; // Missing doc comments
sw . WriteLine ( ) ;
sw . WriteLine ( "partial class {0}" , Settings . OutputClass ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
sw . WriteLine ( ) ;
sw . WriteLine ( "internal static partial class {0}" , Settings . ImportsClass ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
//sw.WriteLine("static {0}() {1} {2}", Settings.ImportsClass, "{", "}"); // Disable BeforeFieldInit
sw . WriteLine ( ) ;
2009-08-21 20:28:14 +00:00
foreach ( Delegate d in delegates . Values )
2009-02-22 10:43:35 +00:00
{
2009-08-03 23:06:05 +00:00
sw . WriteLine ( "[System.Security.SuppressUnmanagedCodeSecurity()]" ) ;
sw . WriteLine (
"[System.Runtime.InteropServices.DllImport({0}.Library, EntryPoint = \"{1}{2}\"{3})]" ,
Settings . OutputClass ,
Settings . FunctionPrefix ,
d . Name ,
d . Name . EndsWith ( "W" ) | | d . Name . EndsWith ( "A" ) ? ", CharSet = CharSet.Auto" : ", ExactSpelling = true"
) ;
sw . WriteLine ( "internal extern static {0};" , d . DeclarationString ( ) ) ;
2009-02-22 10:43:35 +00:00
}
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
}
2009-02-28 19:29:34 +00:00
2009-02-22 10:43:35 +00:00
#endregion
#region void WriteWrappers
public void WriteWrappers ( BindStreamWriter sw , FunctionCollection wrappers , Dictionary < string , string > CSTypes )
{
Trace . WriteLine ( String . Format ( "Writing wrappers to:\t{0}.{1}" , Settings . OutputNamespace , Settings . OutputClass ) ) ;
sw . WriteLine ( "#pragma warning disable 3019" ) ; // CLSCompliant attribute
sw . WriteLine ( "#pragma warning disable 1591" ) ; // Missing doc comments
2009-03-25 21:48:14 +00:00
sw . WriteLine ( "#pragma warning disable 1572" ) ; // Wrong param comments
sw . WriteLine ( "#pragma warning disable 1573" ) ; // Missing param comments
2009-02-22 10:43:35 +00:00
sw . WriteLine ( ) ;
2009-08-15 17:35:20 +00:00
sw . WriteLine ( "partial class {0}" , Settings . OutputClass ) ;
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
//sw.WriteLine("static {0}() {1} {2}", className, "{", "}"); // Static init in GLHelper.cs
sw . WriteLine ( ) ;
2009-03-08 00:46:58 +00:00
int current = 0 ;
2009-02-22 10:43:35 +00:00
foreach ( string key in wrappers . Keys )
{
if ( ( ( Settings . Compatibility & Settings . Legacy . NoSeparateFunctionNamespaces ) = = Settings . Legacy . None ) & & key ! = "Core" )
{
2009-02-28 19:29:34 +00:00
if ( ! Char . IsDigit ( key [ 0 ] ) )
{
sw . WriteLine ( "public static partial class {0}" , key ) ;
}
2009-02-22 10:43:35 +00:00
else
{
2009-02-28 19:29:34 +00:00
// Identifiers cannot start with a number:
2009-02-22 10:43:35 +00:00
sw . WriteLine ( "public static partial class {0}{1}" , Settings . ConstantPrefix , key ) ;
}
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
}
2009-05-30 15:28:52 +00:00
wrappers [ key ] . Sort ( ) ;
2009-02-22 10:43:35 +00:00
foreach ( Function f in wrappers [ key ] )
{
2009-10-27 22:37:05 +00:00
current = WriteWrapper ( sw , current , f ) ;
2009-02-22 10:43:35 +00:00
}
if ( ( ( Settings . Compatibility & Settings . Legacy . NoSeparateFunctionNamespaces ) = = Settings . Legacy . None ) & & key ! = "Core" )
{
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
sw . WriteLine ( ) ;
}
}
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
}
2009-10-27 22:37:05 +00:00
private static int WriteWrapper ( BindStreamWriter sw , int current , Function f )
{
if ( ( Settings . Compatibility & Settings . Legacy . NoDocumentation ) = = 0 )
{
Console . WriteLine ( "Creating docs for #{0} ({1})" , current + + , f . Name ) ;
WriteDocumentation ( sw , f ) ;
}
WriteMethod ( sw , f ) ;
return current ;
}
private static void WriteMethod ( BindStreamWriter sw , Function f )
{
if ( ! f . CLSCompliant )
{
sw . WriteLine ( "[System.CLSCompliant(false)]" ) ;
}
sw . WriteLine ( "[AutoGenerated(Category = \"{0}\", Version = \"{1}\", EntryPoint = \"{2}\")]" ,
f . Category , f . Version , Settings . FunctionPrefix + f . WrappedDelegate . Name ) ;
sw . WriteLine ( "public static " ) ;
sw . Write ( f ) ;
sw . WriteLine ( ) ;
}
private static void WriteDocumentation ( BindStreamWriter sw , Function f )
{
try
{
string path = Path . Combine ( Settings . DocPath , Settings . FunctionPrefix + f . WrappedDelegate . Name + ".xml" ) ;
if ( ! File . Exists ( path ) )
path = Path . Combine ( Settings . DocPath , Settings . FunctionPrefix +
f . TrimmedName + ".xml" ) ;
if ( ! File . Exists ( path ) )
path = Path . Combine ( Settings . DocPath , Settings . FunctionPrefix + f . TrimmedName . TrimEnd ( numbers ) + ".xml" ) ;
if ( File . Exists ( path ) )
{
DocProcessor doc_processor = new DocProcessor ( Path . Combine ( Settings . DocPath , Settings . DocFile ) ) ;
sw . WriteLine ( doc_processor . ProcessFile ( path ) ) ;
}
}
catch ( FileNotFoundException )
{ }
}
2009-02-22 10:43:35 +00:00
#endregion
#region void WriteTypes
public void WriteTypes ( BindStreamWriter sw , Dictionary < string , string > CSTypes )
{
sw . WriteLine ( ) ;
foreach ( string s in CSTypes . Keys )
{
sw . WriteLine ( "using {0} = System.{1};" , s , CSTypes [ s ] ) ;
}
}
#endregion
2009-02-28 19:29:34 +00:00
#region void WriteEnums
2009-02-22 10:43:35 +00:00
public void WriteEnums ( BindStreamWriter sw , EnumCollection enums )
{
//sw.WriteLine("#pragma warning disable 3019"); // CLSCompliant attribute
sw . WriteLine ( "#pragma warning disable 1591" ) ; // Missing doc comments
sw . WriteLine ( ) ;
if ( ( Settings . Compatibility & Settings . Legacy . NestedEnums ) ! = Settings . Legacy . None )
Trace . WriteLine ( String . Format ( "Writing enums to:\t{0}.{1}.{2}" , Settings . OutputNamespace , Settings . OutputClass , Settings . NestedEnumsClass ) ) ;
else
Trace . WriteLine ( String . Format ( "Writing enums to:\t{0}" , Settings . EnumsOutput ) ) ;
if ( ( Settings . Compatibility & Settings . Legacy . ConstIntEnums ) = = Settings . Legacy . None )
{
if ( ( Settings . Compatibility & Settings . Legacy . NestedEnums ) ! = Settings . Legacy . None & &
! String . IsNullOrEmpty ( Settings . NestedEnumsClass ) )
{
sw . WriteLine ( "public class Enums" ) ;
sw . WriteLine ( "{" ) ;
sw . Indent ( ) ;
}
2009-08-21 20:28:14 +00:00
foreach ( Enum @enum in enums . Values )
2009-02-22 10:43:35 +00:00
{
sw . Write ( @enum ) ;
sw . WriteLine ( ) ;
}
if ( ( Settings . Compatibility & Settings . Legacy . NestedEnums ) ! = Settings . Legacy . None & &
! String . IsNullOrEmpty ( Settings . NestedEnumsClass ) )
{
sw . Unindent ( ) ;
sw . WriteLine ( "}" ) ;
}
}
else
{
// Tao legacy mode: dump all enums as constants in GLClass.
2009-08-21 20:28:14 +00:00
foreach ( Constant c in enums [ Settings . CompleteEnumName ] . ConstantCollection . Values )
2009-02-22 10:43:35 +00:00
{
// Print constants avoiding circular definitions
if ( c . Name ! = c . Value )
{
sw . WriteLine ( String . Format (
"public const int {0} = {2}((int){1});" ,
c . Name . StartsWith ( Settings . ConstantPrefix ) ? c . Name : Settings . ConstantPrefix + c . Name ,
Char . IsDigit ( c . Value [ 0 ] ) ? c . Value : c . Value . StartsWith ( Settings . ConstantPrefix ) ? c . Value : Settings . ConstantPrefix + c . Value ,
c . Unchecked ? "unchecked" : "" ) ) ;
}
else
{
}
}
}
}
#endregion
2009-02-28 19:29:34 +00:00
#region void WriteLicense
2009-03-08 18:08:35 +00:00
public void WriteLicense ( BindStreamWriter sw )
2009-02-28 19:29:34 +00:00
{
2009-03-08 18:08:35 +00:00
sw . WriteLine ( File . ReadAllText ( Path . Combine ( Settings . InputPath , Settings . LicenseFile ) ) ) ;
2009-02-28 19:29:34 +00:00
sw . WriteLine ( ) ;
}
#endregion
2009-02-22 10:43:35 +00:00
#endregion
}
}