/// <summary> /// Construct a CommandParameterArray from the original parameter. /// </summary> /// <param name="otherParam"></param> /// <param name="ctx"></param> /// <param name="parentCommand"></param> public CommandParameterArrayLength(CommandParameter otherParam, RegistryContext ctx, Command parentCommand) : base(otherParam, ctx, parentCommand) { if (otherParam == null) throw new ArgumentNullException("otherParam"); }
/// <summary> /// Construct a CommandParameterUnsafe from the original parameter. /// </summary> /// <param name="otherParam"></param> /// <param name="ctx"></param> /// <param name="parentCommand"></param> public CommandParameterUnsafe(CommandParameter otherParam, RegistryContext ctx, Command parentCommand) : base(otherParam) { if (otherParam == null) throw new ArgumentNullException("otherParam"); if (IsCompatible(ctx, parentCommand, otherParam)) { _IsPointer = true; } }
internal static CommandParameter GetArrayLengthParameter(CommandParameter param, RegistryContext ctx, Command parentCommand) { List<CommandParameter> arrayLengthParams = parentCommand.Parameters.FindAll(delegate(CommandParameter item) { return (parentCommand.Parameters.FindIndex(delegate(CommandParameter subitem) { return (item.Length == param.Name); }) >= 0); }); if (arrayLengthParams.Count > 0) return (arrayLengthParams[0]); else return (null); }
/// <summary> /// Construct a CommandParameterStrong from the original parameter. /// </summary> /// <param name="otherParam"></param> /// <param name="ctx"></param> /// <param name="parentCommand"></param> public CommandParameterStrong(CommandParameter otherParam, RegistryContext ctx, Command parentCommand) : base(otherParam) { if (otherParam == null) throw new ArgumentNullException("otherParam"); if (IsCompatible(otherParam, ctx, parentCommand)) { Type = otherParam.Group; mIsStrong = true; } }
internal static new bool IsCompatible(RegistryContext ctx, Command parentCommand, CommandParameter param) { if (!param.IsManagedArray || param.Length == null) return (false); int sizeParamIndex = parentCommand.Parameters.FindIndex(delegate (CommandParameter item) { return (item.Name == param.Length); }); if (sizeParamIndex < 0) return (false); return (true); }
/// <summary> /// Copy constructor. /// </summary> /// <param name="otherParam"> /// Another CommandParameter to be copied. /// </param> protected CommandParameter(CommandParameter otherParam) { if (otherParam == null) throw new ArgumentNullException("otherParam"); Group = otherParam.Group; Length = otherParam.Length; Type = otherParam.Type; TypeDecorators = new List<string>(otherParam.TypeDecorators); Name = otherParam.Name; OverridenParameter = otherParam; }
internal static bool IsCompatible(CommandParameter param, RegistryContext ctx, Command parentCommand) { // 'bool' parameters are in Boolean group: conditions below will pass if (param.GetImplementationType(ctx, parentCommand) == "bool") return (false); // Unsafe parameters are not allowed, Group is a requirement if (!param.IsSafe || param.Group == null) return (false); // Check actual existence of strongly typed enum return (ctx.Registry.Groups.FindIndex(delegate(EnumerantGroup item) { return (item.Name == param.Group); }) >= 0); }
/// <summary> /// Construct a CommandParameterOut from the original parameter. /// </summary> /// <param name="otherParam"></param> /// <param name="ctx"></param> /// <param name="parentCommand"></param> public CommandParameterOut(CommandParameter otherParam, RegistryContext ctx, Command parentCommand, bool strong) : base(otherParam) { if (otherParam == null) throw new ArgumentNullException("otherParam"); if (IsCompatible(ctx, parentCommand, otherParam)) Length = "1"; else if (strong && CommandParameterStrong.IsCompatible(ctx, parentCommand, otherParam)) { Type = otherParam.Group; mIsStrong = true; } }
/// <summary> /// Construct a CommandParameterPinned from the original parameter. /// </summary> /// <param name="otherParam"></param> /// <param name="ctx"></param> /// <param name="parentCommand"></param> public CommandParameterPinned(CommandParameter otherParam, RegistryContext ctx, Command parentCommand, bool strong) : base(otherParam) { if (otherParam == null) throw new ArgumentNullException("otherParam"); if (IsCompatible(ctx, parentCommand, otherParam)) { Type = "Object"; TypeDecorators.Clear(); mIsPinned = true; } else if (strong && CommandParameterStrong.IsCompatible(ctx, parentCommand, otherParam)) { Type = otherParam.Group; } }
internal static bool IsCompatible(RegistryContext ctx, Command command, CommandParameter param) { // Already "out" param? if (param.GetImplementationTypeModifier(ctx, command) == "out") return (false); string implementationType = param.ManagedImplementationType; // Type[] + IsGetImplementation -> out Type // Type[] + OutParam -> out Type // Type[] + OutParamLast -> out Type if ((param.IsConstant == false) && implementationType.EndsWith("[]") && (param.Length != "1") && ((command.Flags & (CommandFlags.OutParam | CommandFlags.OutParamLast)) != 0)) return (true); return (false); }
internal static bool IsCompatible(RegistryContext ctx, Command command, CommandParameter param) { switch (ctx.Class.ToLower()) { case "gl": break; default: return (false); } if (param.GetImplementationType(ctx, command) != "IntPtr") return (false); if (Regex.IsMatch(param.Name, "offset")) return (false); if (param.IsConstant || command.IsGetImplementation(ctx)) return (true); return (false); }
internal static bool IsArrayLengthParameter(CommandParameter param, RegistryContext ctx, Command parentCommand) { CommandParameter arrayParameter = GetArrayLengthParameter(param, ctx, parentCommand); return (arrayParameter != null && arrayParameter.IsManagedArray); }
internal static new bool IsCompatible(RegistryContext ctx, Command command, CommandParameter param) { // Pointer types ends with an '*' return(param.GetImportType(command).EndsWith("*")); }
/// <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("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)); })); }
/// <summary> /// Generate the command implementation (generate one object variant). /// </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_GenOneObject(SourceStreamWriter sw, RegistryContext ctx) { List <CommandParameter> commandParams = new List <CommandParameter>(); string implementationName = GetImplementationName(ctx); if (implementationName.EndsWith("ies")) { implementationName = implementationName.Substring(0, implementationName.Length - 3) + "y"; } else if (implementationName.EndsWith("s")) { implementationName = implementationName.Substring(0, implementationName.Length - 1); } foreach (CommandParameter commandParameter in Parameters) { commandParams.Add(new CommandParameterArrayLength(commandParameter, ctx, this)); } List <CommandParameterArrayLength> arrayParameters = new List <CommandParameterArrayLength>(); List <CommandParameter> signatureParams = commandParams.FindAll(delegate(CommandParameter item) { bool compatible = CommandParameterArrayLength.IsCompatible(ctx, this, item); bool arrayLengthParam = CommandParameterArrayLength.IsArrayLengthParameter(item, ctx, this); if (compatible) { arrayParameters.Add((CommandParameterArrayLength)item); } return(!compatible && !arrayLengthParam); }); Debug.Assert(arrayParameters.Count == 1); CommandParameterArrayLength returnParameter = arrayParameters[0]; string returnParameterType = returnParameter.GetImplementationType(ctx, this); // Remove [] returnParameterType = returnParameterType.Substring(0, returnParameterType.Length - 2); // Signature GenerateImplementation_Signature(sw, ctx, signatureParams, implementationName, returnParameterType); // Implementation block sw.WriteLine("{"); sw.Indent(); #region Local Variables sw.WriteLine("{0}[] {1} = new {0}[1];", returnParameterType, ReturnVariableName); #endregion #region Implementation Call sw.WriteIdentation(); sw.Write("{0}(", GetImplementationName(ctx)); #region Parameters for (int i = 0; i < commandParams.Count; i++) { CommandParameter param = commandParams[i]; if (CommandParameterArrayLength.IsArrayLengthParameter(param, ctx, this)) { continue; } else if (CommandParameterArrayLength.IsCompatible(ctx, this, param)) { sw.Write(ReturnVariableName); } else if (CommandParameterStrong.IsCompatible(ctx, this, param)) { param.WriteImplementationParam(sw, ctx, this); } else { param.WriteDelegateParam(sw, ctx, this); } if (i != commandParams.Count - 1) { sw.Write(", "); } } #endregion sw.Write(");"); sw.WriteLine(); sw.WriteLine("return ({0}[0]);", ReturnVariableName); #endregion sw.Unindent(); sw.WriteLine("}"); }
internal static bool IsCompatible(RegistryContext ctx, Command command, CommandParameter param) { // Pointer types ands with an '*' return (param.ImportType.EndsWith("*")); }
public static CommandItem.ParameterItemFlags GetCommandParameterFlags(Command command, CommandParameter arg) { if (command == null) throw new ArgumentNullException("command"); if (arg == null) throw new ArgumentNullException("arg"); CommandItem.ParameterItemFlags parameterFlags = CommandItem.ParameterItemFlags.None; foreach (CommandItem commandItem in _CommandFlagsDatabase.Commands) { if (Regex.IsMatch(command.Prototype.Name, commandItem.Name)) { foreach (CommandItem.ParameterItem parameterItem in commandItem.Parameters) { if (parameterItem.Id == arg.Name) parameterFlags |= parameterItem.Flags; } } } return (parameterFlags); }
public static string GetCommandArgumentAlternativeName(Command command, CommandParameter arg) { if (command == null) throw new ArgumentNullException("command"); if (arg == null) throw new ArgumentNullException("arg"); foreach (CommandItem commandItem in _CommandFlagsDatabase.Commands) { if (Regex.IsMatch(command.Prototype.Name, commandItem.Name)) { foreach (CommandItem.ParameterItem parameterItem in commandItem.Parameters) { if (parameterItem.Id == arg.Name) return (parameterItem.Rename); } } } // arg.Name return (null); }
/// <summary> /// Generate the command implementation (fixed variant). /// </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_Default(SourceStreamWriter sw, RegistryContext ctx, List <CommandParameter> commandParams) { List <Command> aliases = new List <Command>(); Command aliasCommand = this; // The implementation returned type string returnType = aliasCommand.GetImplementationReturnType(ctx); // Is fixed implementation bool fixedImplementation = IsFixedImplementation(ctx, commandParams) || IsSafeMarshalImplementation(ctx, commandParams); aliases.Add(this); aliases.AddRange(Aliases); // Signature GenerateImplementation_Signature(sw, ctx, commandParams); // Implementation block sw.WriteLine("{"); sw.Indent(); #region Debug Assertions // Debug assertions foreach (CommandParameter param in commandParams) { param.WriteDebugAssertion(sw, ctx, this); } #endregion #region Local Variables // Local variable: returned value if (HasReturnValue) { sw.WriteLine("{0} {1};", DelegateReturnType, ReturnVariableName); sw.WriteLine(); } #endregion #region Unsafe Block (Open) if (fixedImplementation) { sw.WriteLine("unsafe {"); // (1) sw.Indent(); foreach (CommandParameter param in commandParams) { param.WriteFixedStatement(sw, ctx, this); } sw.WriteLine("{"); // (2) sw.Indent(); } #endregion sw.WriteLine("Debug.Assert(Delegates.{0} != null, \"{0} not implemented\");", aliasCommand.DelegateName); #region Delegate Call sw.WriteIdentation(); // Local return value if (HasReturnValue) { sw.Write("{0} = ", ReturnVariableName); } sw.Write("Delegates.{0}(", aliasCommand.DelegateName); #region Parameters for (int i = 0; i < commandParams.Count; i++) { CommandParameter param = commandParams[i]; param.WriteDelegateParam(sw, ctx, this); if (i != Parameters.Count - 1) { sw.Write(", "); } } #endregion sw.Write(")"); sw.Write(";"); sw.WriteLine(); #endregion #region Call Log // Log command sw.WriteIdentation(); sw.Write("LogCommand(\"{0}\"", aliasCommand.ImportName); // Return value if (HasReturnValue) { sw.Write(", "); CommandParameter.WriteCallLogArgParam(sw, GetReturnValueExpression(ctx), returnType); } else { sw.Write(", null"); } // Arguments if (commandParams.Count > 0) { sw.Write(", "); for (int i = 0; i < commandParams.Count; i++) { commandParams[i].WriteCallLogArgParam(sw, ctx, this); if (i < commandParams.Count - 1) { sw.Write(", "); } } } // End LogCommand sw.WriteLine(");"); #endregion #region Unsafe Block (Close) if (fixedImplementation) { sw.Unindent(); sw.WriteLine("}"); // (2) CLOSED sw.Unindent(); sw.WriteLine("}"); // (1) CLOSED } #endregion // Check call errors if ((Flags & CommandFlags.NoGetError) == 0) { string returnValue = "null"; // Optionally pass the returned value to error checking method if (HasReturnValue && !IsUnsafeImplementationSignature(ctx, commandParams)) { returnValue = ReturnVariableName; } sw.WriteLine("DebugCheckErrors({0});", returnValue); } // Returns value if (HasReturnValue) { sw.WriteLine(); sw.WriteLine("return ({0});", GetReturnValueExpression(ctx)); } sw.Unindent(); sw.WriteLine("}"); }
/// <summary> /// Generate the command implementation (pinned variant). /// </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_Pinned(SourceStreamWriter sw, RegistryContext ctx, List <CommandParameter> commandParams) { // Signature GenerateImplementation_Signature(sw, ctx, commandParams); // Implementation block sw.WriteLine("{"); sw.Indent(); #region Pinned Object Block (Open) foreach (CommandParameter param in commandParams) { param.WritePinnedVariable(sw, ctx, this); } sw.WriteLine("try {"); sw.Indent(); #endregion #region Implementation Call sw.WriteIdentation(); if (HasReturnValue) { sw.Write("return ("); } sw.Write("{0}(", GetImplementationName(ctx)); #region Parameters for (int i = 0; i < commandParams.Count; i++) { CommandParameter param = commandParams[i]; param.WriteDelegateParam(sw, ctx, this); if (i != commandParams.Count - 1) { sw.Write(", "); } } #endregion sw.Write(")"); if (HasReturnValue) { sw.Write(")"); } sw.Write(";"); sw.WriteLine(); #endregion #region Pinned Object Block (Close) sw.Unindent(); sw.WriteLine("} finally {"); sw.Indent(); foreach (CommandParameter param in commandParams) { param.WriteUnpinCommand(sw, ctx, this); } sw.Unindent(); sw.WriteLine("}"); #endregion sw.Unindent(); sw.WriteLine("}"); }
public static CommandItem.ParameterItemFlags GetCommandParameterFlags(Command command, CommandParameter arg) { if (command == null) { throw new ArgumentNullException("command"); } if (arg == null) { throw new ArgumentNullException("arg"); } CommandItem.ParameterItemFlags parameterFlags = CommandItem.ParameterItemFlags.None; foreach (CommandItem commandItem in _CommandFlagsDatabase.Commands) { if (Regex.IsMatch(command.Prototype.Name, commandItem.Name)) { foreach (CommandItem.ParameterItem parameterItem in commandItem.Parameters) { if (parameterItem.Id == arg.Name) { parameterFlags |= parameterItem.Flags; } } } } return(parameterFlags); }