/// <summary> /// Merges the given enum into the enum list. If an enum of the same name exists, /// it merges their respective constants. /// </summary> /// <param name="enums"></param> /// <param name="t"></param> internal static void Merge(EnumCollection enums, Enum t) { if (!enums.ContainsKey(t.Name)) { enums.Add(t.Name, t); } else { Enum e = enums[t.Name]; foreach (Constant c in t.ConstantCollection.Values) { Merge(e, c); } } }
static bool IsEnum(string s, EnumCollection enums) { return enums.ContainsKey(s); }
static bool IsEnum(string s, EnumCollection enums) { return(enums.ContainsKey(s)); }
private EnumCollection ReadEnums(XPathNavigator nav) { EnumCollection enums = new EnumCollection(); Enum all = new Enum() { Name = Settings.CompleteEnumName }; if (nav != null) { var reuse_list = new List <KeyValuePair <Enum, string> >(); // First pass: collect all available tokens and enums foreach (XPathNavigator node in nav.SelectChildren("enum", String.Empty)) { Enum e = new Enum() { Name = node.GetAttribute("name", String.Empty).Trim(), Type = node.GetAttribute("type", String.Empty).Trim() }; e.Obsolete = node.GetAttribute("obsolete", String.Empty).Trim(); if (String.IsNullOrEmpty(e.Name)) { throw new InvalidOperationException(String.Format("Empty name for enum element {0}", node.ToString())); } // It seems that all flag collections contain "Mask" in their names. // This looks like a heuristic, but it holds 100% in practice // (checked all enums to make sure). e.IsFlagCollection = e.Name.ToLower().Contains("mask"); foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element)) { Constant c = null; switch (param.Name) { case "token": c = new Constant { Name = param.GetAttribute("name", String.Empty).Trim(), Value = param.GetAttribute("value", String.Empty).Trim() }; break; case "use": c = new Constant { Name = param.GetAttribute("token", String.Empty).Trim(), Reference = param.GetAttribute("enum", String.Empty).Trim(), Value = param.GetAttribute("token", String.Empty).Trim(), }; break; case "reuse": var reuse_enum = param.GetAttribute("enum", String.Empty).Trim(); reuse_list.Add(new KeyValuePair <Enum, string>(e, reuse_enum)); break; default: throw new NotSupportedException(); } if (c != null) { Utilities.Merge(all, c); try { if (!e.ConstantCollection.ContainsKey(c.Name)) { e.ConstantCollection.Add(c.Name, c); } else if (e.ConstantCollection[c.Name].Value != c.Value) { var existing = e.ConstantCollection[c.Name]; if (existing.Reference != null && c.Reference == null) { e.ConstantCollection[c.Name] = c; } else if (existing.Reference == null && c.Reference != null) { // Keep existing } else { Console.WriteLine("[Warning] Conflicting token {0}.{1} with value {2} != {3}", e.Name, c.Name, e.ConstantCollection[c.Name].Value, c.Value); } } } catch (ArgumentException ex) { Console.WriteLine("[Warning] Failed to add constant {0} to enum {1}: {2}", c.Name, e.Name, ex.Message); } } } Utilities.Merge(enums, e); } // Second pass: resolve "reuse" directives restart: foreach (var pair in reuse_list) { var e = pair.Key; var reuse = pair.Value; var count = e.ConstantCollection.Count; if (enums.ContainsKey(reuse)) { var reuse_enum = enums[reuse]; foreach (var token in reuse_enum.ConstantCollection.Values) { Utilities.Merge(e, token); } } else { Console.WriteLine("[Warning] Reuse token not found: {0}", reuse); } if (count != e.ConstantCollection.Count) { // Restart resolution of reuse directives whenever // we modify an enum. This is the simplest (brute) way // to resolve chains of reuse directives: // e.g. enum A reuses B which reuses C goto restart; } } } Utilities.Merge(enums, all); return(enums); }
public virtual EnumCollection ReadEnums(StreamReader specFile) { Trace.WriteLine("Reading opengl enumerant specs."); Trace.Indent(); EnumCollection enums = new EnumCollection(); // complete_enum contains all opengl enumerants. Bind.Structures.Enum complete_enum = new Bind.Structures.Enum(); 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 Bind.Structures.Enum e = new Bind.Structures.Enum(); 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]; uint number; if (UInt32.TryParse(words[2].Replace("0x", String.Empty), System.Globalization.NumberStyles.AllowHexSpecifier, null, out number)) { // The value is a number, check if it should be unchecked. if (number > 0x7FFFFFFF) { c.Unchecked = true; } } else { // The value is not a number. Strip the prefix. if (words[2].StartsWith(Settings.ConstantPrefix)) words[2] = words[2].Substring(Settings.ConstantPrefix.Length); // If the name now starts with a digit (doesn't matter whether we // stripped "GL_" above), add a "GL_" prefix. // (e.g. GL_4_BYTES). if (Char.IsDigit(words[2][0])) words[2] = Settings.ConstantPrefix + words[2]; } 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]; } //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. Trace.WriteLine(String.Format("Conflict: Enum {0} already exists, merging constants.", e.Name)); foreach (Constant t in e.ConstantCollection.Values) { Utilities.Merge(enums[e.Name], t); } } //enums.Add(e); } //SpecTranslator.Merge(enums, complete_enum); } while (!specFile.EndOfStream); enums.Add(complete_enum.Name, complete_enum); Trace.Unindent(); return enums; }
public virtual EnumCollection ReadEnums(StreamReader specFile) { Trace.WriteLine("Reading opengl enumerant specs."); Trace.Indent(); EnumCollection enums = new EnumCollection(); // complete_enum contains all opengl enumerants. Enum complete_enum = new Enum(); 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 Enum e = new Enum(); 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]; } 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)); } //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; }
public virtual EnumCollection ReadEnums(StreamReader specFile) { Trace.WriteLine("Reading opengl enumerant specs."); Trace.Indent(); EnumCollection enums = new EnumCollection(); // complete_enum contains all opengl enumerants. Enum complete_enum = new Enum(); 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 Enum e = new Enum(); 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]; } 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)); } //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 breaks 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); }
void TranslateType(Bind.Structures.Type type, XPathNavigator function_override, XPathNavigator overrides, EnumProcessor enum_processor, EnumCollection enums, string category, string apiname) { Bind.Structures.Enum @enum; string s; category = enum_processor.TranslateEnumName(category); // Try to find out if it is an enum. If the type exists in the normal GLEnums list, use this. // Special case for Boolean which is there simply because C89 does not support bool types. // We don't really need that in C# bool normal = enums.TryGetValue(type.CurrentType, out @enum) || enums.TryGetValue(enum_processor.TranslateEnumName(type.CurrentType), out @enum); // Translate enum types type.IsEnum = false; if (normal && @enum.Name != "GLenum" && @enum.Name != "Boolean") { type.IsEnum = true; if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None) { type.QualifiedType = "int"; } else { // Some functions and enums have the same names. // Make sure we reference the enums rather than the functions. if (normal) { type.QualifiedType = String.Format("{0}.{1}", Settings.EnumsOutput, @enum.Name); } } } else if (Generator.GLTypes.TryGetValue(type.CurrentType, out s)) { // Check if the parameter is a generic GLenum. If it is, search for a better match, // otherwise fallback to Settings.CompleteEnumName (named 'All' by default). if (s.Contains("GLenum") /*&& !String.IsNullOrEmpty(category)*/) { type.IsEnum = true; if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None) { type.QualifiedType = "int"; } else { // Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc) // Note: for backwards compatibility we use "category" only for the gl api. // glcore, gles1 and gles2 use the All enum instead. if (apiname == "gl" && enums.ContainsKey(category)) { type.QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput, Settings.NamespaceSeparator, enum_processor.TranslateEnumName(category)); } else { type.QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput, Settings.NamespaceSeparator, Settings.CompleteEnumName); } } } else { // Todo: what is the point of this here? It is overwritten below. // A few translations for consistency switch (type.CurrentType.ToLower()) { case "string": type.QualifiedType = "String"; break; } type.QualifiedType = s; } } type.CurrentType = Generator.CSTypes.ContainsKey(type.CurrentType) ? Generator.CSTypes[type.CurrentType] : type.CurrentType; // Make sure that enum parameters follow enum overrides, i.e. // if enum ErrorCodes is overriden to ErrorCode, then parameters // of type ErrorCodes should also be overriden to ErrorCode. XPathNavigator enum_override = overrides.SelectSingleNode( EnumProcessor.GetOverridesPath(apiname, type.CurrentType)); if (enum_override != null) { // For consistency - many overrides use string instead of String. if (enum_override.Value == "string") type.QualifiedType = "String"; else if (enum_override.Value == "StringBuilder") type.QualifiedType = "StringBuilder"; else type.CurrentType = enum_override.Value; } if (type.CurrentType == "IntPtr" && String.IsNullOrEmpty(type.PreviousType)) type.Pointer = 0; if (type.Pointer >= 3) { System.Diagnostics.Trace.WriteLine(String.Format( "[Error] Type '{0}' has a high pointer level. Bindings will be incorrect.", type)); } if (!type.IsEnum) { // Remove qualifier if type is not an enum // Resolves issues when replacing / overriding // an enum parameter with a non-enum type type.QualifiedType = type.CurrentType; } }
EnumCollection ReadEnums(XPathNavigator nav) { EnumCollection enums = new EnumCollection(); Enum all = new Enum() { Name = Settings.CompleteEnumName }; if (nav != null) { var reuse_list = new List<KeyValuePair<Enum, string>>(); // First pass: collect all available tokens and enums foreach (XPathNavigator node in nav.SelectChildren("enum", String.Empty)) { Enum e = new Enum() { Name = node.GetAttribute("name", String.Empty).Trim(), Type = node.GetAttribute("type", String.Empty).Trim() }; if (String.IsNullOrEmpty(e.Name)) throw new InvalidOperationException(String.Format("Empty name for enum element {0}", node.ToString())); // It seems that all flag collections contain "Mask" in their names. // This looks like a heuristic, but it holds 100% in practice // (checked all enums to make sure). e.IsFlagCollection = e.Name.ToLower().Contains("mask"); foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element)) { Constant c = null; switch (param.Name) { case "token": c = new Constant { Name = param.GetAttribute("name", String.Empty).Trim(), Value = param.GetAttribute("value", String.Empty).Trim() }; break; case "use": c = new Constant { Name = param.GetAttribute("token", String.Empty).Trim(), Reference = param.GetAttribute("enum", String.Empty).Trim(), Value = param.GetAttribute("token", String.Empty).Trim(), }; break; case "reuse": var reuse_enum = param.GetAttribute("enum", String.Empty).Trim(); reuse_list.Add(new KeyValuePair<Enum, string>(e, reuse_enum)); break; default: throw new NotSupportedException(); } if (c != null) { Utilities.Merge(all, c); try { if (!e.ConstantCollection.ContainsKey(c.Name)) { e.ConstantCollection.Add(c.Name, c); } else if (e.ConstantCollection[c.Name].Value != c.Value) { var existing = e.ConstantCollection[c.Name]; if (existing.Reference != null && c.Reference == null) { e.ConstantCollection[c.Name] = c; } else if (existing.Reference == null && c.Reference != null) { // Keep existing } else { Console.WriteLine("[Warning] Conflicting token {0}.{1} with value {2} != {3}", e.Name, c.Name, e.ConstantCollection[c.Name].Value, c.Value); } } } catch (ArgumentException ex) { Console.WriteLine("[Warning] Failed to add constant {0} to enum {1}: {2}", c.Name, e.Name, ex.Message); } } } Utilities.Merge(enums, e); } // Second pass: resolve "reuse" directives restart: foreach (var pair in reuse_list) { var e = pair.Key; var reuse = pair.Value; var count = e.ConstantCollection.Count; if (enums.ContainsKey(reuse)) { var reuse_enum = enums[reuse]; foreach (var token in reuse_enum.ConstantCollection.Values) { Utilities.Merge(e, token); } } else { Console.WriteLine("[Warning] Reuse token not found: {0}", reuse); } if (count != e.ConstantCollection.Count) { // Restart resolution of reuse directives whenever // we modify an enum. This is the simplest (brute) way // to resolve chains of reuse directives: // e.g. enum A reuses B which reuses C goto restart; } } } Utilities.Merge(enums, all); return enums; }
/// <summary> /// Replces the Value of the given constant with the value referenced by the [c.Reference, c.Value] pair. /// </summary> /// <param name="c">The Constant to translate</param> /// <param name="enums">The list of enums to check.</param> /// <param name="auxEnums">The list of auxilliary enums to check.</param> /// <returns>True if the reference was found; false otherwise.</returns> public static bool TranslateConstantWithReference(Constant c, EnumCollection enums, EnumCollection auxEnums) { if (!String.IsNullOrEmpty(c.Reference)) { Constant referenced_constant; if (enums.ContainsKey(c.Reference) && enums[c.Reference].ConstantCollection.ContainsKey(c.Value)) { TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums); referenced_constant = (enums[c.Reference].ConstantCollection[c.Value] as Constant); } else if (auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value)) { TranslateConstantWithReference(auxEnums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums); referenced_constant = (auxEnums[c.Reference].ConstantCollection[c.Value] as Constant); } else { Console.WriteLine("[Warning] Reference {0} not found for token {1}.", c.Reference, c); return false; } //else throw new InvalidOperationException(String.Format("Unknown Enum \"{0}\" referenced by Constant \"{1}\"", // c.Reference, c.ToString())); c.Value = referenced_constant.Value; c.Reference = null; c.Unchecked = referenced_constant.Unchecked; } return true; }
void TranslateType(Bind.Structures.Type type, XPathNavigator function_override, XPathNavigator overrides, EnumProcessor enum_processor, EnumCollection enums, string category, string apiname) { Bind.Structures.Enum @enum; string s; category = enum_processor.TranslateEnumName(category); // Try to find out if it is an enum. If the type exists in the normal GLEnums list, use this. // Special case for Boolean - it is an enum, but it is dumb to use that instead of the 'bool' type. bool normal = enums.TryGetValue(type.CurrentType, out @enum); // Translate enum types type.IsEnum = false; if (normal && @enum.Name != "GLenum" && @enum.Name != "Boolean") { type.IsEnum = true; if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None) { type.QualifiedType = "int"; } else { // Some functions and enums have the same names. // Make sure we reference the enums rather than the functions. if (normal) { type.QualifiedType = type.CurrentType.Insert(0, String.Format("{0}.", Settings.EnumsOutput)); } } } else if (Generator.GLTypes.TryGetValue(type.CurrentType, out s)) { // Check if the parameter is a generic GLenum. If it is, search for a better match, // otherwise fallback to Settings.CompleteEnumName (named 'All' by default). if (s.Contains("GLenum") /*&& !String.IsNullOrEmpty(category)*/) { type.IsEnum = true; if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None) { type.QualifiedType = "int"; } else { // Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc) // Note: for backwards compatibility we use "category" only for the gl api. // glcore, gles1 and gles2 use the All enum instead. if (apiname == "gl" && enums.ContainsKey(category)) { type.QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput, Settings.NamespaceSeparator, enum_processor.TranslateEnumName(category)); } else { type.QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput, Settings.NamespaceSeparator, Settings.CompleteEnumName); } } } else { // Todo: what is the point of this here? It is overwritten below. // A few translations for consistency switch (type.CurrentType.ToLower()) { case "string": type.QualifiedType = "String"; break; } type.QualifiedType = s; } } type.CurrentType = Generator.CSTypes.ContainsKey(type.CurrentType) ? Generator.CSTypes[type.CurrentType] : type.CurrentType; // Make sure that enum parameters follow enum overrides, i.e. // if enum ErrorCodes is overriden to ErrorCode, then parameters // of type ErrorCodes should also be overriden to ErrorCode. XPathNavigator enum_override = overrides.SelectSingleNode( EnumProcessor.GetOverridesPath(apiname, type.CurrentType)); if (enum_override != null) { // For consistency - many overrides use string instead of String. if (enum_override.Value == "string") { type.QualifiedType = "String"; } else if (enum_override.Value == "StringBuilder") { type.QualifiedType = "StringBuilder"; } else { type.CurrentType = enum_override.Value; } } if (type.CurrentType == "IntPtr" && String.IsNullOrEmpty(type.PreviousType)) { type.Pointer = 0; } if (type.Pointer >= 3) { System.Diagnostics.Trace.WriteLine(String.Format( "[Error] Type '{0}' has a high pointer level. Bindings will be incorrect.", type)); } if (!type.IsEnum) { // Remove qualifier if type is not an enum // Resolves issues when replacing / overriding // an enum parameter with a non-enum type type.QualifiedType = type.CurrentType; } }
public virtual EnumCollection ReadEnums(StreamReader specFile) { Trace.WriteLine("Reading opengl enumerant specs."); Trace.Indent(); EnumCollection enums = new EnumCollection(); // complete_enum contains all opengl enumerants. Bind.Structures.Enum complete_enum = new Bind.Structures.Enum(); 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 Bind.Structures.Enum e = new Bind.Structures.Enum(); 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]; uint number; if (UInt32.TryParse(words[2].Replace("0x", String.Empty), System.Globalization.NumberStyles.AllowHexSpecifier, null, out number)) { // The value is a number, check if it should be unchecked. if (number > 0x7FFFFFFF) { c.Unchecked = true; } } else { // The value is not a number. Strip the prefix. if (words[2].StartsWith(Settings.ConstantPrefix)) { words[2] = words[2].Substring(Settings.ConstantPrefix.Length); } // If the name now starts with a digit (doesn't matter whether we // stripped "GL_" above), add a "GL_" prefix. // (e.g. GL_4_BYTES). if (Char.IsDigit(words[2][0])) { words[2] = Settings.ConstantPrefix + words[2]; } } 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]; } //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. Trace.WriteLine(String.Format("Conflict: Enum {0} already exists, merging constants.", e.Name)); foreach (Constant t in e.ConstantCollection.Values) { Utilities.Merge(enums[e.Name], t); } } //enums.Add(e); } //SpecTranslator.Merge(enums, complete_enum); }while (!specFile.EndOfStream); enums.Add(complete_enum.Name, complete_enum); Trace.Unindent(); return(enums); }
/// <summary> /// Replces the Value of the given constant with the value referenced by the [c.Reference, c.Value] pair. /// </summary> /// <param name="c">The Constant to translate</param> /// <param name="enums">The list of enums to check.</param> /// <param name="auxEnums">The list of auxilliary enums to check.</param> /// <returns>True if the reference was found; false otherwise.</returns> public static bool TranslateConstantWithReference(Constant c, EnumCollection enums, EnumCollection auxEnums) { if (c == null) throw new ArgumentNullException("c"); if (enums == null) throw new ArgumentNullException("enums"); if (++CurrentReferenceDepth >= MaxReferenceDepth) throw new InvalidOperationException("Enum specification contains cycle"); if (!String.IsNullOrEmpty(c.Reference)) { Constant referenced_constant; if (enums.ContainsKey(c.Reference) && enums[c.Reference].ConstantCollection.ContainsKey(c.Value)) { // Transitively translate the referenced token // Todo: this may cause loops if two tokens reference each other. // Add a max reference depth and bail out? TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value], enums, auxEnums); referenced_constant = (enums[c.Reference].ConstantCollection[c.Value]); } else if (auxEnums != null && auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value)) { // Legacy from previous generator incarnation. // Todo: merge everything into enums and get rid of auxEnums. TranslateConstantWithReference(auxEnums[c.Reference].ConstantCollection[c.Value], enums, auxEnums); referenced_constant = (auxEnums[c.Reference].ConstantCollection[c.Value]); } else if (enums.ContainsKey(Settings.CompleteEnumName) && enums[Settings.CompleteEnumName].ConstantCollection.ContainsKey(c.Value)) { // Try the All enum var reference = enums[Settings.CompleteEnumName].ConstantCollection[c.Value]; if (reference.Reference == null) referenced_constant = (enums[Settings.CompleteEnumName].ConstantCollection[c.Value]); else { --CurrentReferenceDepth; return false; } } else { --CurrentReferenceDepth; return false; } //else throw new InvalidOperationException(String.Format("Unknown Enum \"{0}\" referenced by Constant \"{1}\"", // c.Reference, c.ToString())); c.Value = referenced_constant.Value; c.Reference = null; } --CurrentReferenceDepth; return true; }