public virtual void WriteCallLogArgParam(SourceStreamWriter sw, RegistryContext ctx, Command parentCommand) { CommandFlagsDatabase.CommandItem.ParameterItemFlags parameterFlags = CommandFlagsDatabase.GetCommandParameterFlags(parentCommand, this); //if (((Type != null) && (Type == "GLenum")) || ((parameterFlags & CommandFlagsDatabase.CommandItem.ParameterItemFlags.LogAsEnum) != 0)) // sw.Write("LogEnumName({0})", ImplementationName); //else if (IsManagedArray && GetImplementationTypeModifier(ctx, parentCommand) != "out") // sw.Write("LogValue({0})", ImplementationName); //else WriteCallLogArgParam(sw, ImplementationName, GetImplementationType(ctx, parentCommand)); }
public string GetImportType(Command parentCommand) { string retype = CommandFlagsDatabase.GetCommandArgumentAlternativeType(parentCommand, this); if (retype != null) { return(TypeMap.CsTypeMap.MapType(retype)); } return(ImportType); }
/// <summary> /// Generate the command import source code. /// </summary> /// <param name="sw"> /// The <see cref="SourceStreamWriter"/> used to write the source code. /// </param> /// <param name="ctx"> /// The <see cref="RegistryContext"/> defining the OpenGL registry information. /// </param> internal void GenerateImport(SourceStreamWriter sw, RegistryContext ctx) { // The SuppressUnmanagedCodeSecurity attribute is used to increase P/Invoke performance sw.WriteLine("[SuppressUnmanagedCodeSecurity()]"); // Import definition CommandFlags commandFlags = CommandFlagsDatabase.GetCommandFlags(this); if ((commandFlags & CommandFlags.SetLastError) != 0) { sw.WriteLine("[DllImport(Library, EntryPoint = \"{0}\", ExactSpelling = true, SetLastError = true)]", ImportName); } else { sw.WriteLine("[DllImport(Library, EntryPoint = \"{0}\", ExactSpelling = true)]", ImportName); } // GLboolean is mapped to 'unsigned char': instruct to marshal return value as 1 byte boolean if (Prototype.Type == "GLboolean") { sw.WriteLine("[return: MarshalAs(UnmanagedType.I1)]"); } // BOOL is mapped to 'unsigned int': instruct to marshal return value as 4 byte boolean if (Prototype.Type == "BOOL") { sw.WriteLine("[return: MarshalAs(UnmanagedType.Bool)]"); } // Import declaration sw.WriteIdentation(); sw.Write("internal extern static "); if (IsSafeImplementation == false) { sw.Write("unsafe "); } sw.Write("{0} {1}(", DelegateReturnType, ImportName); int paramCount = Parameters.Count; foreach (CommandParameter param in Parameters) { sw.Write("{0} {1}", param.ImportType, param.ImportName); paramCount--; if (paramCount > 0) { sw.Write(", "); } } sw.Write(");"); sw.WriteLine(); }
/// <summary> /// Get the name of the command implementation (with overloading). /// </summary> /// <param name="ctx"> /// A <see cref="RegistryContext"/> used for manipulating the command import name. /// </param> internal string GetImplementationName(RegistryContext ctx) { string overridenName = CommandFlagsDatabase.GetCommandImplementationName(this); if (overridenName == null) { string implementationName = GetImplementationNameBase(ctx); return(ctx.WordsDictionary.GetOverridableName(ctx, implementationName)); } else { return(overridenName); } }
public virtual void WriteDelegateParam(SourceStreamWriter sw, RegistryContext ctx, Command parentCommand) { if (IsFixed(ctx, parentCommand) == false) { string modifier = CommandFlagsDatabase.GetCommandArgumentModifier(parentCommand, this); if (modifier != null) { sw.Write(modifier + " "); } sw.Write(GetDelegateCallVarName(parentCommand)); } else { sw.Write(FixedLocalVarName); } }
public string GetDelegateType(RegistryContext ctx, Command parentCommand) { string modifier = CommandFlagsDatabase.GetCommandArgumentModifier(parentCommand, this); string implementationType = GetImportType(parentCommand); // String + Length!=null -> [Out] StringBuilder if ((IsConstant == false) && (implementationType == "String") && (Length != null) && ((parentCommand.IsGetImplementation(ctx) || ((parentCommand.Flags & CommandFlags.OutParam) != 0)))) { implementationType = "StringBuilder"; } // Support 'ref' argument if ((modifier == "ref" || modifier == "out") && implementationType.EndsWith("*")) { implementationType = modifier + " " + implementationType.Substring(0, implementationType.Length - 1); } return(implementationType.Trim()); }
/// <summary> /// /// </summary> /// <param name="ctx"></param> /// <param name="parentCommand"></param> /// <returns></returns> /// <remarks> /// <para> /// In the generale case, the implementation type corresponds to <see cref="ManagedImplementationType"/>. /// </para> /// <para> /// In the case the implementation type is a managed array, but the specification assert a length equals to /// 1, and <paramref name="parentCommand"/> is a "Get" implementation, the implementation type is converted /// to a basic type, with an "out" modifier. /// </para> /// </remarks> public virtual string GetImplementationType(RegistryContext ctx, Command parentCommand) { string modifier = CommandFlagsDatabase.GetCommandArgumentModifier(parentCommand, this); string implementationType = GetManagedImplementationType(parentCommand); // Type[] + Length=1 -> out Type if ((IsConstant == false) && implementationType.EndsWith("[]") && (Length == "1") && ((parentCommand.IsGetImplementation(ctx) || ((parentCommand.Flags & CommandFlags.OutParam) != 0)))) { implementationType = implementationType.Substring(0, implementationType.Length - 2); } // String + Length!=null && !IsConst -> [Out] StringBuilder (in Get commands) if ((IsConstant == false) && (implementationType == "String") && (Length != null) && ((parentCommand.IsGetImplementation(ctx) || ((parentCommand.Flags & CommandFlags.OutParam) != 0)))) { implementationType = "StringBuilder"; } // Support 'ref' argument if ((modifier == "ref" || modifier == "out") && implementationType.EndsWith("[]")) { implementationType = modifier + " " + implementationType.Substring(0, implementationType.Length - 2); } return(implementationType); }
/// <summary> /// Determine whether this CommandParameter must be used in a fixed context. /// </summary> /// <param name="ctx"></param> /// <param name="parentCommand"></param> /// <returns></returns> internal virtual bool IsFixed(RegistryContext ctx, Command parentCommand) { string modifier = CommandFlagsDatabase.GetCommandArgumentModifier(parentCommand, this); if (modifier == "ref" || modifier == "out") { return(false); } string implementationType = GetManagedImplementationType(parentCommand); string importType = GetImportType(parentCommand); if (Regex.IsMatch(implementationType.ToLower(), @"(string|bool)\[\]")) { return(Regex.IsMatch(importType.ToLower(), @"(string|bool)\*")); } if (implementationType.EndsWith("[]")) { return(true); } return(false); }
internal void GenerateSource(SourceStreamWriter sw, RegistryContext ctx) { if (sw == null) { throw new ArgumentNullException("sw"); } if (ctx == null) { throw new ArgumentNullException("ctx"); } bool bitmask = Enums.TrueForAll(delegate(Enumerant item) { Enumerant actualEnumerant = ctx.Registry.GetEnumerant(item.Name); return(actualEnumerant == null || actualEnumerant.ParentEnumerantBlock.Type == "bitmask"); }); // Collect group enumerants by their value Dictionary <string, List <Enumerant> > groupEnums = new Dictionary <string, List <Enumerant> >(); // ...include all enums defined in this group foreach (Enumerant item in Enums) { Enumerant itemValue = ctx.Registry.GetEnumerant(item.Name); if (itemValue != null) { if (!groupEnums.ContainsKey(itemValue.Value)) { groupEnums.Add(itemValue.Value, new List <Enumerant>()); } groupEnums[itemValue.Value].Add(itemValue); } } // Modify canonical enumeration (value/block/group) definition CommandFlagsDatabase.EnumerantItem enumerantExtension = CommandFlagsDatabase.FindEnumerant(Name); if (enumerantExtension != null) { // ...override group information if (enumerantExtension.Type != null) { switch (enumerantExtension.Type) { case "bitmask": bitmask = true; break; } } // ...include all enums to be added by additional configuration foreach (string addedEnum in enumerantExtension.AddEnumerants) { Enumerant addedEnumValue = ctx.Registry.GetEnumerant(addedEnum); if (addedEnumValue != null) { if (!groupEnums.ContainsKey(addedEnumValue.Value)) { groupEnums.Add(addedEnumValue.Value, new List <Enumerant>()); } // Note: since specification can be updated while the CommandFlags.xml is not in synch, the specification // may defined missed enumerant values. In this case do not add enumerant value if (groupEnums[addedEnumValue.Value].Contains(addedEnumValue) == false) { groupEnums[addedEnumValue.Value].Add(addedEnumValue); } } } } // Make enumerants distinct (discard duplicated enumerants, mainly from extensions _ARB, _EXT, ...) List <Enumerant> uniqueEnums = new List <Enumerant>(); foreach (KeyValuePair <string, List <Enumerant> > pair in groupEnums) { if (pair.Value.Count > 1) { Enumerant shorterNameEnum = null; foreach (Enumerant item in pair.Value) { if ((shorterNameEnum == null) || (shorterNameEnum.Name.Length > item.Name.Length)) { shorterNameEnum = item; } } uniqueEnums.Add(shorterNameEnum); } else { uniqueEnums.Add(pair.Value[0]); } } sw.WriteLine("/// <summary>"); sw.WriteLine("/// Strongly typed enumeration {0}.", Name); sw.WriteLine("/// </summary>"); if (bitmask) { sw.WriteLine("[Flags()]"); } sw.WriteLine("public enum {0}{1}", Name, bitmask ? " : uint" : String.Empty); sw.WriteLine("{"); sw.Indent(); foreach (Enumerant enumerant in uniqueEnums) { List <Enumerant> allEnums = groupEnums[enumerant.Value]; string bindingName = enumerant.EnumAlias == null ? enumerant.ImplementationName : enumerant.EnumAlias.ImplementationName; string camelCase = SpecificationStyle.GetCamelCase(bindingName); sw.WriteLine("/// <summary>"); if (allEnums.Count > 1) { StringBuilder sb = new StringBuilder(); sb.Append("Strongly typed for value "); for (int i = 0; i < allEnums.Count; i++) { sb.Append(allEnums[i].Name); if (i < allEnums.Count - 1) { sb.Append(", "); } } sb.Append("."); foreach (string docLine in RegistryDocumentation.SplitDocumentationLines(sb.ToString())) { sw.WriteLine("/// {0}", docLine); } } else { sw.WriteLine("/// Strongly typed for value {0}.", enumerant.Name); } sw.WriteLine("/// </summary>"); sw.WriteLine("{0} = Gl.{1},", camelCase, bindingName); sw.WriteLine(); } sw.Unindent(); sw.WriteLine("}"); }
internal void GenerateSource(SourceStreamWriter sw, RegistryContext ctx) { if (sw == null) { throw new ArgumentNullException("sw"); } if (ctx == null) { throw new ArgumentNullException("ctx"); } bool bitmask = Enums.TrueForAll(delegate(Enumerant item) { Enumerant actualEnumerant = ctx.Registry.GetEnumerant(item.Name); return(actualEnumerant == null || actualEnumerant.ParentEnumerantBlock.Type == "bitmask"); }); // Collect group enumerants by their value Dictionary <string, List <Enumerant> > groupEnums = new Dictionary <string, List <Enumerant> >(); // ...include all enums defined in this group foreach (Enumerant item in Enums) { Enumerant itemValue = ctx.Registry.GetEnumerant(item.Name); if (itemValue != null) { if (!groupEnums.ContainsKey(itemValue.Value)) { groupEnums.Add(itemValue.Value, new List <Enumerant>()); } groupEnums[itemValue.Value].Add(itemValue); } } // Modify canonical enumeration (value/block/group) definition CommandFlagsDatabase.EnumerantItem enumerantExtension = CommandFlagsDatabase.FindEnumerant(Name); if (enumerantExtension != null) { // ...override group information if (enumerantExtension.Type != null) { switch (enumerantExtension.Type) { case "bitmask": bitmask = true; break; } } // ...include all enums to be added by additional configuration foreach (string addedEnum in enumerantExtension.AddEnumerants) { Enumerant addedEnumValue = ctx.Registry.GetEnumerant(addedEnum); if (addedEnumValue != null) { if (!groupEnums.ContainsKey(addedEnumValue.Value)) { groupEnums.Add(addedEnumValue.Value, new List <Enumerant>()); } // Note: since specification can be updated while the CommandFlags.xml is not in synch, the specification // may defined missed enumerant values. In this case do not add enumerant value if (groupEnums[addedEnumValue.Value].Contains(addedEnumValue) == false) { groupEnums[addedEnumValue.Value].Add(addedEnumValue); } } } } // Make enumerants distinct (discard duplicated enumerants, mainly from extensions _ARB, _EXT, ...) List <Enumerant> uniqueEnums = new List <Enumerant>(); foreach (KeyValuePair <string, List <Enumerant> > pair in groupEnums) { if (pair.Value.Count > 1) { List <Enumerant> uniqueNames = new List <Enumerant>(); foreach (Enumerant item in pair.Value) { if (item.Alias != null) { continue; } if (item.EnumAlias != null) { continue; } if (uniqueNames.FindIndex(delegate(Enumerant item1) { return(item.Name.StartsWith(item1.Name)); }) >= 0) { continue; } if (uniqueNames.FindIndex(delegate(Enumerant item1) { return(item1.Name.StartsWith(item.Name)); }) >= 0) { uniqueNames.RemoveAll(delegate(Enumerant item1) { return(item1.Name.StartsWith(item.Name)); }); } uniqueNames.Add(item); } uniqueEnums.AddRange(uniqueNames); } else { uniqueEnums.AddRange(pair.Value); } } sw.WriteLine("/// <summary>"); sw.WriteLine("/// Strongly typed enumeration {0}.", Name); sw.WriteLine("/// </summary>"); if (bitmask) { sw.WriteLine("[Flags()]"); } sw.WriteLine("public enum {0}{1}", Name, bitmask ? " : uint" : String.Empty); sw.WriteLine("{"); sw.Indent(); foreach (Enumerant enumerant in uniqueEnums) { List <Enumerant> allEnums = groupEnums[enumerant.Value]; string bindingName = enumerant.EnumAlias == null ? enumerant.ImplementationName : enumerant.EnumAlias.ImplementationName; string camelCase = SpecificationStyle.GetCamelCase(bindingName); if (enumerantExtension != null && enumerantExtension.ItemPrefix != null && camelCase.StartsWith(enumerantExtension.ItemPrefix)) { camelCase = camelCase.Substring(enumerantExtension.ItemPrefix.Length); } sw.WriteLine("/// <summary>"); if (allEnums.Count > 1) { StringBuilder sb = new StringBuilder(); sb.Append("Strongly typed for value "); for (int i = 0; i < allEnums.Count; i++) { sb.Append(allEnums[i].Name); if (i < allEnums.Count - 1) { sb.Append(", "); } } sb.Append("."); foreach (string docLine in RegistryDocumentation.SplitDocumentationLines(sb.ToString())) { sw.WriteLine("/// {0}", docLine); } } else { sw.WriteLine("/// Strongly typed for value {0}.", enumerant.Name); } sw.WriteLine("/// </summary>"); Enumerant enumvalue = ctx.Registry.GetEnumerant(ctx.Class.ToUpperInvariant() + "_" + bindingName); string classDefaultApi = ctx.Class.ToLower(); if (enumvalue != null) { // RequiredByFeature foreach (IFeature feature in enumvalue.RequiredBy) { sw.WriteLine(feature.GenerateRequiredByAttribute(null, classDefaultApi)); } // RequiredByFeature (from aliases) Note: not sure that Profile is considered here foreach (Enumerant aliasOf in enumvalue.AliasOf) { foreach (IFeature feature in aliasOf.RequiredBy) { sw.WriteLine(feature.GenerateRequiredByAttribute(null, classDefaultApi)); } } // RemovedByFeature foreach (IFeature feature in enumvalue.RemovedBy) { sw.WriteLine(feature.GenerateRemovedByAttribute(classDefaultApi)); } } sw.WriteLine("{0} = {1}.{2},", camelCase, ctx.Class, bindingName); sw.WriteLine(); } sw.Unindent(); sw.WriteLine("}"); }
/// <summary> /// Generate the command implementation signature and the method documentation. /// </summary> /// <param name="sw"> /// The <see cref="SourceStreamWriter"/> used to write the source code. /// </param> /// <param name="ctx"> /// The <see cref="RegistryContext"/> defining the OpenGL registry information. /// </param> /// <param name="commandParams"> /// A <see cref="T:List{CommandParameter}"/> determining the method overload. /// </param> private void GenerateImplementation_Signature(SourceStreamWriter sw, RegistryContext ctx, List <CommandParameter> commandParams, string implementationName, string returnType) { #if !DEBUG // Documentation RegistryDocumentation.GenerateDocumentation(sw, ctx, this, commandParams); #endif foreach (IFeature feature in RequiredBy) { sw.WriteLine("[RequiredByFeature(\"{0}\")]", feature.Name); } foreach (IFeature feature in RemovedBy) { sw.WriteLine("[RemovedByFeature(\"{0}\")]", feature.Name); } #region Signature sw.WriteIdentation(); // Signature sw.Write("{0} static ", CommandFlagsDatabase.GetCommandVisibility(this)); if (IsUnsafeImplementationSignature(ctx, commandParams)) { sw.Write("unsafe "); } sw.Write("{0} {1}(", returnType, implementationName); // Signature - Parameters int paramCount = commandParams.FindAll(delegate(CommandParameter item) { return(!item.IsImplicit(ctx, this)); }).Count; foreach (CommandParameter param in commandParams) { // Skip in signature implicit parameters if (param.IsImplicit(ctx, this)) { continue; } string paramAttributes = param.GetImplementationTypeAttributes(ctx, this); string paramModifier = param.GetImplementationTypeModifier(ctx, this); if (paramAttributes != null) { sw.Write("{0} ", paramAttributes); } if (paramModifier != null) { sw.Write("{0} ", paramModifier); } if ((paramCount == 1) && (param.IsManagedArray) && ((Flags & CommandFlags.VariadicParams) != 0)) { sw.Write("params "); } sw.Write("{0} {1}", param.GetImplementationType(ctx, this), param.ImplementationName); paramCount--; if (paramCount > 0) { sw.Write(", "); } } sw.Write(")"); sw.WriteLine(); #endregion }
/// <summary> /// Append definitions recognized in a header file. /// </summary> /// <param name="path"> /// A <see cref="System.String"/> that specified the path of the header file. /// </param> public void AppendHeader(string path, string headerFeatureName) { if (path == null) { throw new ArgumentNullException(nameof(path)); } string headerText; // Read the whole header using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (StreamReader sr = new StreamReader(fs)) { headerText = sr.ReadToEnd(); } } // Remove comments string inlineComment = @"//(.*?)\r?\n"; string blockComment = @"/\*(.*?)\*/"; headerText = Regex.Replace(headerText, String.Format("{0}|{1}", inlineComment, blockComment), delegate(Match match) { if (match.Value.StartsWith("/*")) { return(String.Empty); } if (match.Value.StartsWith("//")) { return(Environment.NewLine); } return(match.Value); }, RegexOptions.Singleline); // Extract C preprocessor #define directives string defineDirective = @"#define (?<Symbol>[\w\d_]+) +(?<Value>.*)\r?\n"; EnumerantBlock definesBlock = new EnumerantBlock(); definesBlock.Group = "Defines"; headerText = Regex.Replace(headerText, defineDirective, delegate(Match match) { // Collect symbol/value if (match.Value.StartsWith("#define ")) { Enumerant enumerant = new Enumerant(); // Replace enumeration macros string enumDefinition = ReplaceEnumMacros(match.Groups["Value"].Value.Trim()); // Replace constants in enumeration value enumDefinition = ReplaceEnumConstants(enumDefinition); enumerant.Name = match.Groups["Symbol"].Value.Trim(); enumerant.Value = enumDefinition; enumerant.ParentEnumerantBlock = definesBlock; bool useDefine = true; if (enumerant.Value.StartsWith("__")) { useDefine = false; } if (enumerant.Value.StartsWith("{") && enumerant.Value.EndsWith("}")) { useDefine = false; } if (useDefine) { definesBlock.Enums.Add(enumerant); // Collect enumerant _Enumerants.Add(enumerant); } return(String.Empty); } return(match.Value); }, RegexOptions.Multiline); // Remove no more necessary C preprocessor string preprocessorDirective = @"#(if|ifndef|else|endif|define|include) ?.*\r?\n"; headerText = Regex.Replace(headerText, preprocessorDirective, String.Empty); // Remove new lines headerText = Regex.Replace(headerText, @"\r?\n", String.Empty); // Remove structures typedefs string structTypedef = @"typedef struct ?\{(.*?)\}( +?)(.*?);"; headerText = Regex.Replace(headerText, structTypedef, String.Empty); // Remove multiple spaces headerText = Regex.Replace(headerText, @" +", " "); // Extract extern "C" scope string externBlock = "extern \"C\" {"; if (headerText.StartsWith(externBlock)) { headerText = headerText.Substring(externBlock.Length, headerText.Length - externBlock.Length - 1); } // Split into statements string[] statements = Regex.Split(headerText, ";"); foreach (string statement in statements) { Match match; // Parse enumeration block if ((match = Regex.Match(statement, @"(typedef )?enum(?<Name> [\w\d_]+)? ?\{(?<Enums>.*)\}(?<Tag> +?[\w\d_]+)?")).Success) { string name; if (match.Groups["Tag"].Success) { name = match.Groups["Tag"].Value.Trim(); } else if (match.Groups["Name"].Success) { name = match.Groups["Name"].Value.Trim(); } else { throw new InvalidOperationException("unable to determine name of enum"); } if (Regex.IsMatch(name, "WF(C|D)boolean")) { continue; } #region Enumeration // Skip enumeration if required CommandFlagsDatabase.EnumerantItem enumItem = CommandFlagsDatabase.FindEnumerant(name); if (enumItem != null && enumItem.Disable) { continue; } EnumerantBlock enumerantBlock = new EnumerantBlock(); enumerantBlock.Group = headerFeatureName; EnumerantGroup enumerantGroup = new EnumerantGroup(); enumerantGroup.Name = name; // Override name if (enumItem != null && enumItem.Alias != null) { enumerantGroup.Name = enumItem.Alias; } // Replace enumeration macros string enumDefinition = ReplaceEnumMacros(match.Groups["Enums"].Value); // Replace constants in enumeration value enumDefinition = ReplaceEnumConstants(enumDefinition); // Parse enumerations string[] enumValues = Regex.Split(enumDefinition, ","); for (int i = 0; i < enumValues.Length; i++) { string enumValue = enumValues[i].Trim(); if ((match = Regex.Match(enumValue, @"(?<Name>(\w|_)+)\s*=\s*(?<Value>.*)")).Success) { Enumerant enumerant = new Enumerant(); enumerant.Name = match.Groups["Name"].Value; enumerant.Value = match.Groups["Value"].Value.Trim(); enumerant.ParentEnumerantBlock = enumerantBlock; enumerantBlock.Enums.Add(enumerant); enumerantGroup.Enums.Add(enumerant); // Collect enumerant _Enumerants.Add(enumerant); } } _Groups.Add(enumerantGroup); #endregion continue; } else if ((match = Regex.Match(statement, CommandExportRegex + @"(?<Return>.*) " + CommandCallConventionRegex + @"(?<Name>.*)\((?<Args>.*)\)" + CommandExitRegex)).Success) { #region Command Command command = new Command(); command.Prototype = new CommandPrototype(); command.Prototype.Type = match.Groups["Return"].Value; command.Prototype.Name = match.Groups["Name"].Value; string[] args = Regex.Split(match.Groups["Args"].Value, ","); for (int i = 0; i < args.Length; i++) { string arg = args[i].Trim(); if (arg == String.Empty) { break; } // '*' denotes types, not names arg = arg.Replace(" **", "** "); arg = arg.Replace(" *", "* "); if ((match = Regex.Match(arg, @"(const +)?(?<Type>(\w|_|\* (const)?|\*)+) +(?<Name>[\w\d_]+)(?<ArraySize>\[([\w\d_]+)?\])?$")).Success) { string arraySize = match.Groups["ArraySize"].Success ? match.Groups["ArraySize"].Value : null; CommandParameter commandParameter = new CommandParameter(); commandParameter.Name = match.Groups["Name"].Value; commandParameter.Type = arraySize != null ? match.Groups["Type"].Value + "*" : match.Groups["Type"].Value; command.Parameters.Add(commandParameter); } else if (arg == "...") { CommandParameter commandParameter = new CommandParameter(); commandParameter.Name = "vaArgs"; commandParameter.Type = "IntPtr"; command.Parameters.Add(commandParameter); } else { throw new InvalidOperationException(String.Format("unable to parse argument '{0}'", arg)); } } _Commands.Add(command); #endregion } } Feature headerFeature = _Features.Find(delegate(Feature item) { return(item.Name == headerFeatureName); }); if (headerFeature == null) { headerFeature = new Feature(); headerFeature.Name = headerFeatureName; headerFeature.Api = Class.ToLowerInvariant(); _Features.Add(headerFeature); } FeatureCommand headerFeatureCommand = new FeatureCommand(); headerFeature.Requirements.Add(headerFeatureCommand); headerFeatureCommand.Enums.AddRange(_Enumerants.ConvertAll(delegate(Enumerant input) { return(new FeatureCommand.Item(input.Name)); })); headerFeatureCommand.Commands.AddRange(_Commands.ConvertAll(delegate(Command input) { return(new FeatureCommand.Item(input.Prototype.Name)); })); }