From 267c6f2ac71f92999e969232431ba04678e7437e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 07:54:39 +0200 Subject: Adding upstream version 4:24.2.0. Signed-off-by: Daniel Baumann --- cli_ure/source/basetypes/assembly.cs | 21 + cli_ure/source/basetypes/cli_basetypes_config | 11 + cli_ure/source/basetypes/uno/Any.cs | 202 ++ cli_ure/source/basetypes/uno/BoundAttribute.cs | 37 + cli_ure/source/basetypes/uno/ExceptionAttribute.cs | 61 + cli_ure/source/basetypes/uno/OnewayAttribute.cs | 34 + .../basetypes/uno/ParameterizedTypeAttribute.cs | 59 + cli_ure/source/basetypes/uno/PolymorphicType.cs | 434 ++++ .../source/basetypes/uno/TypeArgumentsAttribute.cs | 75 + .../basetypes/uno/TypeParametersAttribute.cs | 56 + cli_ure/source/climaker/climaker_app.cxx | 674 ++++++ cli_ure/source/climaker/climaker_emit.cxx | 2279 ++++++++++++++++++++ cli_ure/source/climaker/climaker_share.h | 258 +++ cli_ure/source/cliuno.snk | Bin 0 -> 596 bytes cli_ure/source/native/assembly.cxx | 26 + cli_ure/source/native/cli_cppuhelper_config | 11 + cli_ure/source/native/native_bootstrap.cxx | 297 +++ cli_ure/source/native/native_share.h | 112 + cli_ure/source/native/path.cxx | 48 + cli_ure/source/scripts/increment_version.pl | 273 +++ cli_ure/source/scripts/subst_template.pl | 124 ++ cli_ure/source/uno_bridge/README.txt | 20 + cli_ure/source/uno_bridge/cli_base.h | 171 ++ cli_ure/source/uno_bridge/cli_bridge.cxx | 321 +++ cli_ure/source/uno_bridge/cli_bridge.h | 113 + cli_ure/source/uno_bridge/cli_data.cxx | 1929 +++++++++++++++++ cli_ure/source/uno_bridge/cli_environment.cxx | 168 ++ cli_ure/source/uno_bridge/cli_environment.h | 105 + cli_ure/source/uno_bridge/cli_proxy.cxx | 1105 ++++++++++ cli_ure/source/uno_bridge/cli_proxy.h | 294 +++ cli_ure/source/uno_bridge/cli_uno.cxx | 277 +++ cli_ure/source/ure/assembly.cs | 21 + cli_ure/source/ure/cli_ure_config | 11 + cli_ure/source/ure/uno/util/DisposeGuard.cs | 50 + cli_ure/source/ure/uno/util/WeakAdapter.cs | 111 + cli_ure/source/ure/uno/util/WeakBase.cs | 135 ++ cli_ure/source/ure/uno/util/WeakComponentBase.cs | 185 ++ 37 files changed, 10108 insertions(+) create mode 100644 cli_ure/source/basetypes/assembly.cs create mode 100644 cli_ure/source/basetypes/cli_basetypes_config create mode 100644 cli_ure/source/basetypes/uno/Any.cs create mode 100644 cli_ure/source/basetypes/uno/BoundAttribute.cs create mode 100644 cli_ure/source/basetypes/uno/ExceptionAttribute.cs create mode 100644 cli_ure/source/basetypes/uno/OnewayAttribute.cs create mode 100644 cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs create mode 100644 cli_ure/source/basetypes/uno/PolymorphicType.cs create mode 100644 cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs create mode 100644 cli_ure/source/basetypes/uno/TypeParametersAttribute.cs create mode 100644 cli_ure/source/climaker/climaker_app.cxx create mode 100644 cli_ure/source/climaker/climaker_emit.cxx create mode 100644 cli_ure/source/climaker/climaker_share.h create mode 100644 cli_ure/source/cliuno.snk create mode 100644 cli_ure/source/native/assembly.cxx create mode 100644 cli_ure/source/native/cli_cppuhelper_config create mode 100644 cli_ure/source/native/native_bootstrap.cxx create mode 100644 cli_ure/source/native/native_share.h create mode 100644 cli_ure/source/native/path.cxx create mode 100644 cli_ure/source/scripts/increment_version.pl create mode 100644 cli_ure/source/scripts/subst_template.pl create mode 100644 cli_ure/source/uno_bridge/README.txt create mode 100644 cli_ure/source/uno_bridge/cli_base.h create mode 100644 cli_ure/source/uno_bridge/cli_bridge.cxx create mode 100644 cli_ure/source/uno_bridge/cli_bridge.h create mode 100644 cli_ure/source/uno_bridge/cli_data.cxx create mode 100644 cli_ure/source/uno_bridge/cli_environment.cxx create mode 100644 cli_ure/source/uno_bridge/cli_environment.h create mode 100644 cli_ure/source/uno_bridge/cli_proxy.cxx create mode 100644 cli_ure/source/uno_bridge/cli_proxy.h create mode 100644 cli_ure/source/uno_bridge/cli_uno.cxx create mode 100644 cli_ure/source/ure/assembly.cs create mode 100644 cli_ure/source/ure/cli_ure_config create mode 100644 cli_ure/source/ure/uno/util/DisposeGuard.cs create mode 100644 cli_ure/source/ure/uno/util/WeakAdapter.cs create mode 100644 cli_ure/source/ure/uno/util/WeakBase.cs create mode 100644 cli_ure/source/ure/uno/util/WeakComponentBase.cs (limited to 'cli_ure/source') diff --git a/cli_ure/source/basetypes/assembly.cs b/cli_ure/source/basetypes/assembly.cs new file mode 100644 index 0000000000..ac99fffd8d --- /dev/null +++ b/cli_ure/source/basetypes/assembly.cs @@ -0,0 +1,21 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +[assembly:System.Reflection.AssemblyDescription( "CLI-UNO: Language Binding specific types" )] +[assembly:System.Reflection.AssemblyCompany( "OpenOffice.org" )] +[assembly:System.Reflection.AssemblyVersion( "@CLI_BASETYPES_NEW_VERSION@" )] diff --git a/cli_ure/source/basetypes/cli_basetypes_config b/cli_ure/source/basetypes/cli_basetypes_config new file mode 100644 index 0000000000..44ef606006 --- /dev/null +++ b/cli_ure/source/basetypes/cli_basetypes_config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/cli_ure/source/basetypes/uno/Any.cs b/cli_ure/source/basetypes/uno/Any.cs new file mode 100644 index 0000000000..ea44d0f3b8 --- /dev/null +++ b/cli_ure/source/basetypes/uno/Any.cs @@ -0,0 +1,202 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; +using System.Text; + +namespace uno +{ + +/** This class can be used as a base class for UNO objects. + It implements the capability to be kept weakly + (unoidl.com.sun.star.uno.XWeak) and it implements + unoidl.com.sun.star.lang.XTypeProvider which is necessary for + using the object from StarBasic. +*/ +public struct Any +{ + private object _value; + private Type _type; + + public static Any VOID = new Any(typeof(void), null); + + private static void checkArgs(Type type, Object value) + { + //value can only be null if type == void + if (type == null + || (value == null + && type != typeof(void) + && type != typeof(object) + && type.IsInterface == false)) + throw new System.Exception( + "uno.Any: Constructor called with illegal arguments!"); + //If value is a polymorphic struct then type must be + //uno.Polymorphic + if (value != null) + { + TypeParametersAttribute t = (TypeParametersAttribute) Attribute.GetCustomAttribute( + value.GetType(), typeof(TypeParametersAttribute)); + if (t != null && !(type is PolymorphicType)) + throw new System.Exception( + "uno.Any: The value has a polymorphic type but the type argument is not " + + "uno.PolymorphicType. Please use the constructor Any(Type, object) and " + + "supply a uno.PolymorphicType as type argument!"); + } + } + + /** constructs an instance. + +

If the arguments are invalid then an exception is thrown.

+ @exception System.Exception + */ + public Any(Type type, object value) + { + checkArgs(type, value); + _type = type; + _value = value; + } + + /** sets the type and value. +

If the arguments ar invalid then an exception is thrown.

+ @exception System.Exception + */ + public void setValue(Type type, object value) + { + checkArgs(type, value); + _type = type; + _value = value; + } + + public Type Type + { + get + { + if (_type == null) + _type = typeof(void); + return _type; + } + } + + public Object Value + { + get + { + return _value; + } + } + + public Any(char value): this(typeof(char), value) + { + } + + public Any(bool value): this(typeof(bool), value) + { + } + + public Any(byte value): this(typeof(byte), value) + { + } + + public Any(short value): this(typeof(short), value) + { + } + + public Any(ushort value): this(typeof(ushort), value) + { + } + + public Any(int value): this(typeof(int), value) + { + } + + public Any(uint value): this(typeof(uint), value) + { + } + + public Any(long value): this(typeof(long), value) + { + } + + public Any(ulong value): this(typeof(ulong), value) + { + } + + public Any(float value): this(typeof(float), value) + { + } + + public Any(double value): this(typeof(double), value) + { + } + + public Any(Type value): this(typeof(Type), value) + { + } + + public Any(string value): this(typeof(string), value) + { + } + + public override string ToString() + { + StringBuilder msg = new StringBuilder("uno.Any { Type= "); + msg.Append(Type.ToString()); + msg.Append(", Value="); + msg.Append(Value.ToString()); + msg.Append("}"); + return msg.ToString(); + } + + public bool hasValue() + { + if (Type == null || Type == typeof(void)) + return false; + return true; + } + + public override bool Equals(object obj) + { + if (obj != null) + { + try + { + return Equals((Any) obj); + } + catch (InvalidCastException) + { + } + } + return false; + } + + public bool Equals(Any obj) + { + return Type.Equals(obj.Type) + && (Value == null ? + obj.Value == null : + Value.Equals(obj.Value)); + } + + public override int GetHashCode() + { + return Type.GetHashCode() ^ (Value != null ? Value.GetHashCode() : 0); + } +} + +} + diff --git a/cli_ure/source/basetypes/uno/BoundAttribute.cs b/cli_ure/source/basetypes/uno/BoundAttribute.cs new file mode 100644 index 0000000000..d899257392 --- /dev/null +++ b/cli_ure/source/basetypes/uno/BoundAttribute.cs @@ -0,0 +1,37 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; + + +namespace uno +{ +/** is used to mark UNO interface attributes as "bound". + +

It corresponds to PropertyAttribute::BOUND. +

+ UNO interface attributes are mapped to CLI properties. + */ +[AttributeUsage(AttributeTargets.Property, Inherited=false)] +public sealed class BoundAttribute: System.Attribute +{ +} + +} + diff --git a/cli_ure/source/basetypes/uno/ExceptionAttribute.cs b/cli_ure/source/basetypes/uno/ExceptionAttribute.cs new file mode 100644 index 0000000000..1c8847b44f --- /dev/null +++ b/cli_ure/source/basetypes/uno/ExceptionAttribute.cs @@ -0,0 +1,61 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; + + +namespace uno +{ +/** is used to mark a UNO method to throw exceptions. + +

A method can be an ordinary interface method, a get or set method from + an interface attribute, or the constructor methods of service creator + classes. If there are no exceptions specified for a method then this + attribute should not be applied. Because a + RuntimeException + can always be thrown it is not specified. Hence no + ExceptionAttribute + should be applied in that case.

+ */ +[AttributeUsage(AttributeTargets.Method, Inherited=false)] +public sealed class ExceptionAttribute: System.Attribute +{ + /** initializes an instance with the specified values. + + @param raises + array of types of Exceptions which are declared in UNOIDL. + It must not be null. + */ + public ExceptionAttribute(Type[] raises) + { + m_raises = raises; + } + + public Type[] Raises + { + get + { + return m_raises; + } + } + + private Type[] m_raises; +} + +} + diff --git a/cli_ure/source/basetypes/uno/OnewayAttribute.cs b/cli_ure/source/basetypes/uno/OnewayAttribute.cs new file mode 100644 index 0000000000..ed8ad85fff --- /dev/null +++ b/cli_ure/source/basetypes/uno/OnewayAttribute.cs @@ -0,0 +1,34 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; + + +namespace uno +{ +/** is used to mark UNO interface methods as being one - way according to the + UNOIDL oneway attribute. +

+ */ +[AttributeUsage(AttributeTargets.Method, Inherited=false)] +public sealed class OnewayAttribute: System.Attribute +{ + +} +} + diff --git a/cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs b/cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs new file mode 100644 index 0000000000..1ff37b280f --- /dev/null +++ b/cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs @@ -0,0 +1,59 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; + + +namespace uno +{ +/** is used to mark a UNO entity to have a parameterized type. + +

Currently it is only applied to members of polymorphic structs. That is structs, + which have a type parameter list. +

+ + @see TypeParametersAttribute + */ +[AttributeUsage(AttributeTargets.Field, Inherited=false)] +public sealed class ParameterizedTypeAttribute: System.Attribute +{ + /** initializes an instance with the specified value. + + @param parameter + the name of parameter from the parameter list from + TypeParametersAttribute + It must not be null. + */ + public ParameterizedTypeAttribute(string parameter) + { + m_parameter = parameter; + } + + public string Type + { + get + { + return m_parameter; + } + } + + private string m_parameter; +} + +} + diff --git a/cli_ure/source/basetypes/uno/PolymorphicType.cs b/cli_ure/source/basetypes/uno/PolymorphicType.cs new file mode 100644 index 0000000000..e996131fc6 --- /dev/null +++ b/cli_ure/source/basetypes/uno/PolymorphicType.cs @@ -0,0 +1,434 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; +using System.Collections; +using System.Reflection; +using System.Globalization; + +namespace uno { + + + +/** represents a polymorphic type. + + This class is used to carry type information for polymorphic struct types + and arrays of polymorphic struct types. These types would be easiest represented + with type templates, which are not available in .NET 1.1. Therefore + the System.Type cannot contain information about template parameters. To + retain this information we use PolymorphicType which directly inherits from + System.Type. The additional information about type parameters are passed + as simple string when creating an instance of PolymorphicType. Usually one + only needs a PolymorphicType when a polymporphic type is put into an + uno.Any. For example, let's assume there is a idl type PolyStruct: + + module test { + struct PolyStruct< T > + { + T member; + }; + }; + + Then one would use it in C# in this way: + + uno.Any myAny = new uno.Any( PolymorphicType.GetType( + typeof(PolyStruct), "unoidl.test.PolyStruct"), + new PolyStruct(true)); + + or if one has a sequence of polymorphic structs: + + uno.Any myAny = new uno.Any( PolymorphicType.GetType( + typeof(PolyStruct), "unoidl.test.PolyStruct[]"), + new PolyStruct[] {new PolyStruct(true)} ); + + + To get a new instance of PolymorphicType one uses the static method + PolymorphicType.GetType. The method ensures that there is only one instance + for each distinct name. For example, if GetType is called multiple times with + the name "unoidl.test.PolyStruct" then the same instance of + PolymorphicType is returned. This makes it possible to compare the instances + by reference, thas is using the operator "==". + + The polymorphic name, which is passed as second argument to PolymorphicType.GetType, + contains a list of type names. Only type names common + to all CLI languages can be used. That is, instead of using names, such as + char, int, float, the names System.Char, System.Int32 and + System.Single are to be used. Spaces are not allowed. + The name will always start with "unoidl", when the type was generated by climaker. + Here are a couple of possible strings: + + unoidl.test.PolyStruct + unoidl.test.PolyStruct + unoidl.test.PolyStruct[] + unoidl.test.PolyStruct> + unoidl.test.PolyStruct[]>[] + + In the future, when the CLI supports templates, we will probably adapt the cli-uno + bridge accordingly to use real template types. Then this class will become obsolete. + */ +public class PolymorphicType: Type +{ + private Type m_base; + private string m_type_name; + + private static Hashtable m_ht_types = Hashtable.Synchronized(new Hashtable(256)); + + /** provides a unique instance of this class. + + This function returns null if the specified type is no polymorphic struct. + + @param type + the type of the polymorphic struct. For example, created by + typeof(unoidl.com.sun.star.beans.Defaulted) + @param name + the full name of the struct (including the type list). + @return + null - the argument type is no valid polymorphic struct or
+ an instance of this class. + @exception System.ArgumentNullException + The argument was null. + */ + public static PolymorphicType GetType(Type type, string name) + { + if (name == null || type == null) + throw new ArgumentNullException( + "cli-uno: uno.PolymorphicType.GetType was called with a null argument"); + //check if the type is either an array of structs or a polymorphic struct. + if (type.IsArray) + { + Type elementType = type; + while ((elementType = elementType.GetElementType()).IsArray); + //unfortunately we cannot check if it is a real polymorphic struct here. + if ( ! elementType.IsClass) + return null; + + + } + else if (Attribute.GetCustomAttribute(type, typeof(uno.TypeParametersAttribute)) + == null) + { + return null; + } + + lock (m_ht_types.SyncRoot) + { + PolymorphicType t = (PolymorphicType) m_ht_types[name]; + if (t == null) + { + t = new PolymorphicType(type, name); + m_ht_types.Add(name, t); + } + return t; + } + } + + private PolymorphicType(Type type, string name) + { + m_type_name = name; + m_base = type; + } + + public string PolymorphicName + { + get + { + return m_type_name; + } + } + + public Type OriginalType + { + get + { + return m_base; + } + } + + + //implementations of abstract methods and properties from base class + public override string Name + { + get + { + return m_base.Name; + } + } + + public override Assembly Assembly + { + get + { + return m_base.Assembly; + } + } + + public override string AssemblyQualifiedName + { + get + { + return m_base.AssemblyQualifiedName; + } + } + + public override Type BaseType + { + get + { + return m_base.BaseType; + } + } + + public override string FullName + { + get + { + return m_base.FullName; + } + } + + public override Guid GUID + { + get + { + return m_base.GUID; + } + } + + public override Module Module + { + get + { + return m_base.Module; + } + } + + public override string Namespace + { + get + { + return m_base.Namespace; + } + } + + public override RuntimeTypeHandle TypeHandle + { + get + { + return m_base.TypeHandle; + } + } + + public override Type UnderlyingSystemType + { + get + { + return m_base.UnderlyingSystemType; + } + } + + public override Type DeclaringType + { + get + { + return m_base.DeclaringType; + } + } + + public override object[] GetCustomAttributes( + bool inherit) + { + return m_base.GetCustomAttributes(inherit); + } + + public override object[] GetCustomAttributes( + Type attributeType, + bool inherit) + { + return m_base.GetCustomAttributes(attributeType, inherit); + } + + public override bool IsDefined( + Type attributeType, + bool inherit) + { + return IsDefined(attributeType, inherit); + } + + protected override TypeAttributes GetAttributeFlagsImpl() + { + return m_base.Attributes; + } + + protected override ConstructorInfo GetConstructorImpl( + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, + ParameterModifier[] modifiers) + { + return m_base.GetConstructor( + bindingAttr, binder, callConvention, types, modifiers); + } + + public override ConstructorInfo[] GetConstructors( + BindingFlags bindingAttr) + { + return m_base.GetConstructors(bindingAttr); + } + + public override Type GetElementType() + { + return m_base.GetElementType(); + } + + public override EventInfo GetEvent( + string name, + BindingFlags bindingAttr) + { + return m_base.GetEvent(name, bindingAttr); + } + + public override EventInfo[] GetEvents( + BindingFlags bindingAttr) + { + return m_base.GetEvents(bindingAttr); + } + + public override FieldInfo GetField( + string name, + BindingFlags bindingAttr) + { + return m_base.GetField(name, bindingAttr); + } + + public override FieldInfo[] GetFields( + BindingFlags bindingAttr) + { + return m_base.GetFields(bindingAttr); + } + + public override Type GetInterface( + string name, bool ignoreCase) + { + return m_base.GetInterface(name, ignoreCase); + } + + public override Type[] GetInterfaces() + { + return m_base.GetInterfaces(); + } + + public override MemberInfo[] GetMembers( + BindingFlags bindingAttr) + { + return m_base.GetMembers(bindingAttr); + } + + protected override MethodInfo GetMethodImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, + ParameterModifier[] modifiers) + { + return m_base.GetMethod( + name, bindingAttr, binder, callConvention, types, modifiers); + } + + public override MethodInfo[] GetMethods( + BindingFlags bindingAttr) + { + return m_base.GetMethods(bindingAttr); + } + + public override Type GetNestedType( + string name, BindingFlags bindingAttr) + { + return m_base.GetNestedType(name, bindingAttr); + } + + public override Type[] GetNestedTypes( + BindingFlags bindingAttr) + { + return m_base.GetNestedTypes(bindingAttr); + } + + public override PropertyInfo[] GetProperties( + BindingFlags bindingAttr) + { + return m_base.GetProperties(bindingAttr); + } + + protected override PropertyInfo GetPropertyImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + Type returnType, + Type[] types, + ParameterModifier[] modifiers) + { + return m_base.GetProperty( + name, bindingAttr, binder, returnType, types, modifiers); + } + + protected override bool HasElementTypeImpl() + { + return m_base.HasElementType; + } + + public override object InvokeMember( + string name, + BindingFlags invokeAttr, + Binder binder, + object target, + object[] args, + ParameterModifier[] modifiers, + CultureInfo culture, + string[] namedParameters) + { + return m_base.InvokeMember( + name, invokeAttr, binder, target, args, modifiers, culture, namedParameters); + } + + protected override bool IsArrayImpl() + { + return m_base.IsArray; + } + + protected override bool IsByRefImpl() + { + return m_base.IsByRef; + } + + protected override bool IsCOMObjectImpl() + { + return m_base.IsCOMObject; + } + + protected override bool IsPointerImpl() + { + return m_base.IsPointer; + } + + protected override bool IsPrimitiveImpl() + { + return m_base.IsPrimitive; + } +} +} diff --git a/cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs b/cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs new file mode 100644 index 0000000000..f2e8c8e39b --- /dev/null +++ b/cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs @@ -0,0 +1,75 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; + + +namespace uno +{ +/** is used to mark a parameterized UNO entity(i.e. struct) + to be an instantiation of a + template with the specified type arguments. + +

Currently only UNO structs can have type parameters.

+ +
+
+    [TypeParameters(new string[]{"T"})]
+    struct Foo {
+      [ParameterizedType("T")]
+      Object member;
+    }
+
+    public interface XFoo {
+       [return:TypeArguments(new string[]{typeof(char)})]
+       Foo func( [TypeArguments(new string[]{typeof(char)})] Foo f);
+    }
+    
+ + @see TypeParametersAttribute + @see ParameterizedTypeAttribute + */ +[AttributeUsage(AttributeTargets.ReturnValue + | AttributeTargets.Parameter + | AttributeTargets.Field, Inherited=false)] +public sealed class TypeArgumentsAttribute: System.Attribute +{ + /** initializes an instance with the specified value. + + @param parameters + arrayay of names representing the types. + It must not be null. + */ + public TypeArgumentsAttribute(Type[] arguments) + { + m_arguments = arguments; + } + + public Type[] Arguments + { + get + { + return m_arguments; + } + } + + private Type[] m_arguments; +} + +} + diff --git a/cli_ure/source/basetypes/uno/TypeParametersAttribute.cs b/cli_ure/source/basetypes/uno/TypeParametersAttribute.cs new file mode 100644 index 0000000000..f6adebaa0b --- /dev/null +++ b/cli_ure/source/basetypes/uno/TypeParametersAttribute.cs @@ -0,0 +1,56 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; + + +namespace uno +{ +/** is used to mark a UNO entity to have type parameters. + +

Currently it is only applied with polymorphic structs. That is structs, + which have a type parameter list. +

+ */ +[AttributeUsage(AttributeTargets.Class, Inherited=false)] +public sealed class TypeParametersAttribute: System.Attribute +{ + /** initializes an instance with the specified value. + + @param parameters + array of names representing the types. + It must not be null. + */ + public TypeParametersAttribute(string[] parameters) + { + m_parameters = parameters; + } + + public string[] Parameters + { + get + { + return m_parameters; + } + } + + private string[] m_parameters; +} + +} + diff --git a/cli_ure/source/climaker/climaker_app.cxx b/cli_ure/source/climaker/climaker_app.cxx new file mode 100644 index 0000000000..b2ba44fef0 --- /dev/null +++ b/cli_ure/source/climaker/climaker_app.cxx @@ -0,0 +1,674 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "sal/config.h" + +#include +#include +#include +#include + +#include "climaker_share.h" + +#include "sal/main.h" +#include "osl/process.h" +#include "osl/file.hxx" +#include "osl/thread.h" +#include "rtl/ustrbuf.hxx" +#include "cppuhelper/bootstrap.hxx" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XSet.hpp" +#include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "unoidl/unoidl.hxx" + +using namespace ::System::Reflection; + + +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace climaker +{ + + +static char const s_usingText [] = +"\n" +"using: climaker [registry-file-1 registry-file-2 ...]\n" +"\n" +"switches:\n" +" -O, --out output assembly file;\n" +" defaults to cli_unotypes.dll if more than one\n" +" registry-file is given, else .dll\n" +" -T, --types types to be generated (if none is given,\n" +" then all types of given registries are emitted\n" +" -X, --extra additional rdb to saturate referenced types in\n" +" given registry file(s); these types will not be\n" +" emitted into the output assembly file\n" +" -r, --reference reference metadata from assembly file\n" +" \n" +" -k, --keyfile keyfile needed for strong name\n" +" --assembly-version sets assembly version\n" +" --assembly-description sets assembly description text\n" +" --assembly-product sets assembly product name\n" +" --assembly-company sets assembly company\n" +" --assembly-copyright sets assembly copyright\n" +" --assembly-trademark sets assembly trademark\n" +" -v, --verbose verbose output to stdout\n" +" -h, --help this message\n" +"\n" +"example: climaker --out cli_mytypes.dll \\\n" +" --reference cli_uretypes.dll \\\n" +" --extra types.rdb \\\n" +" mytypes.rdb\n" +"\n"; + +struct OptionInfo +{ + char const * m_name; + sal_uInt32 m_name_length; + sal_Unicode m_short_option; + bool m_has_argument; +}; + +bool g_bVerbose = false; + + +static const OptionInfo s_option_infos [] = { + { RTL_CONSTASCII_STRINGPARAM("out"), 'O', true }, + { RTL_CONSTASCII_STRINGPARAM("types"), 'T', true }, + { RTL_CONSTASCII_STRINGPARAM("extra"), 'X', true }, + { RTL_CONSTASCII_STRINGPARAM("reference"), 'r', true }, + { RTL_CONSTASCII_STRINGPARAM("keyfile"), 'k', true }, + { RTL_CONSTASCII_STRINGPARAM("delaySign"), 'd', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-version"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-description"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-product"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-company"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-copyright"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-trademark"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false }, + { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false } +}; + + +static OptionInfo const * get_option_info( + OUString const & opt, sal_Unicode copt = '\0' ) +{ + for ( sal_Int32 pos = 0; + pos < (sizeof (s_option_infos) / sizeof (OptionInfo)); + ++pos ) + { + OptionInfo const & option_info = s_option_infos[ pos ]; + + if (opt.getLength() > 0) + { + if (opt.equalsAsciiL( + option_info.m_name, option_info.m_name_length ) && + (copt == '\0' || copt == option_info.m_short_option)) + { + return &option_info; + } + } + else + { + OSL_ASSERT( copt != '\0' ); + if (copt == option_info.m_short_option) + { + return &option_info; + } + } + } + OSL_FAIL( + OUStringToOString( opt, osl_getThreadTextEncoding() ).getStr() ); + return 0; +} + + +static bool is_option( + OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + OSL_ASSERT( option_info != 0 ); + if (osl_getCommandArgCount() <= *pIndex) + return false; + + OUString arg; + osl_getCommandArg( *pIndex, &arg.pData ); + sal_Int32 len = arg.getLength(); + + if (len < 2 || arg[ 0 ] != '-') + return false; + + if (len == 2 && arg[ 1 ] == option_info->m_short_option) + { + ++(*pIndex); + return true; + } + if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare( + arg.pData->buffer + 2, option_info->m_name ) == 0) + { + ++(*pIndex); + return true; + } + return false; +} + + +static inline bool read_option( + bool * flag, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + bool ret = is_option( option_info, pIndex ); + if (ret) + *flag = true; + return ret; +} + + +static bool read_argument( + OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + if (is_option( option_info, pIndex )) + { + if (*pIndex < osl_getCommandArgCount()) + { + osl_getCommandArg( *pIndex, &pValue->pData ); + ++(*pIndex); + return true; + } + --(*pIndex); + } + return false; +} + + +static OUString const & path_get_working_dir() +{ + static OUString s_workingDir; + if (! s_workingDir.getLength()) + osl_getProcessWorkingDir( &s_workingDir.pData ); + return s_workingDir; +} + + +static OUString path_make_absolute_file_url( OUString const & path ) +{ + OUString file_url; + oslFileError rc = osl_getFileURLFromSystemPath( + path.pData, &file_url.pData ); + if (osl_File_E_None == rc) + { + OUString abs; + rc = osl_getAbsoluteFileURL( + path_get_working_dir().pData, file_url.pData, &abs.pData ); + if (osl_File_E_None == rc) + { + return abs; + } + else + { + throw RuntimeException( + "cannot make absolute: " + file_url ); + } + } + else + { + throw RuntimeException( + "cannot get file url from system path: " + path ); + } +} + +} + +using namespace ::climaker; + + +SAL_IMPLEMENT_MAIN() +{ + sal_uInt32 nCount = osl_getCommandArgCount(); + if (0 == nCount) + { + puts( s_usingText ); + return 0; + } + + int ret = 0; + css::uno::Reference< XComponentContext > xContext; + + try + { + OptionInfo const * info_help = + get_option_info( "help" ); + OptionInfo const * info_verbose = + get_option_info( "verbose" ); + OptionInfo const * info_out = + get_option_info( "out" ); + OptionInfo const * info_types = + get_option_info( "types" ); + OptionInfo const * info_reference = + get_option_info( "reference" ); + OptionInfo const * info_extra = + get_option_info( "extra" ); + OptionInfo const * info_keyfile = + get_option_info( "keyfile" ); + OptionInfo const * info_delaySign = + get_option_info( "delaySign" ); + OptionInfo const * info_version = + get_option_info( "assembly-version" ); + OptionInfo const * info_product = + get_option_info( "assembly-product" ); + OptionInfo const * info_description = + get_option_info( "assembly-description" ); + OptionInfo const * info_company = + get_option_info( "assembly-company" ); + OptionInfo const * info_copyright = + get_option_info( "assembly-copyright" ); + OptionInfo const * info_trademark = + get_option_info( "assembly-trademark" ); + + OUString output; + std::vector< OUString > mandatory_registries; + std::vector< OUString > extra_registries; + std::vector< OUString > extra_assemblies; + std::vector< OUString > explicit_types; + OUString version, product, description, company, copyright, trademark, + keyfile, delaySign; + + OUString cmd_arg; + for ( sal_uInt32 nPos = 0; nPos < nCount; ) + { + // options + if (is_option( info_help, &nPos )) + { + puts( s_usingText ); + return 0; + } + else if (read_argument( &cmd_arg, info_types, &nPos )) + { + sal_Int32 index = 0; + do + { + explicit_types.push_back( + cmd_arg.getToken( 0, ';', index ) ); + } + while (index >= 0); + } + else if (read_argument( &cmd_arg, info_extra, &nPos )) + { + extra_registries.push_back( + path_make_absolute_file_url( cmd_arg ) ); + } + else if (read_argument( &cmd_arg, info_reference, &nPos )) + { + extra_assemblies.push_back( + path_make_absolute_file_url( cmd_arg ) ); + } + else if (!read_option( &g_bVerbose, info_verbose, &nPos ) && + !read_argument( &output, info_out, &nPos ) && + !read_argument( &version, info_version, &nPos ) && + !read_argument( &description, info_description, &nPos ) && + !read_argument( &product, info_product, &nPos ) && + !read_argument( &company, info_company, &nPos ) && + !read_argument( ©right, info_copyright, &nPos ) && + !read_argument( &trademark, info_trademark, &nPos ) && + !read_argument( &keyfile, info_keyfile, &nPos ) && + !read_argument( &delaySign, info_delaySign, &nPos )) + { + osl_getCommandArg( nPos, &cmd_arg.pData ); + ++nPos; + cmd_arg = cmd_arg.trim(); + if (cmd_arg.getLength() > 0) + { + if (cmd_arg[ 0 ] == '-') // is option + { + OptionInfo const * option_info = 0; + if (cmd_arg.getLength() > 2 && + cmd_arg[ 1 ] == '-') + { + // long option + option_info = get_option_info( + cmd_arg.copy( 2 ), '\0' ); + } + else if (cmd_arg.getLength() == 2 && + cmd_arg[ 1 ] != '-') + { + // short option + option_info = get_option_info( + OUString(), cmd_arg[ 1 ] ); + } + if (option_info == 0) + { + throw RuntimeException("unknown option " + cmd_arg + "! Use climaker --help to print all options."); + } + else + { + OSL_FAIL( "unhandled valid option?!" ); + if (option_info->m_has_argument) + ++nPos; + } + } + else + { + mandatory_registries.push_back( + path_make_absolute_file_url( cmd_arg ) ); + } + } + } + } + + // bootstrap uno + xContext = ::cppu::defaultBootstrap_InitialComponentContext(); + css::uno::Reference< container::XHierarchicalNameAccess > xTDmgr( + xContext->getValueByName( + "/singletons/com.sun.star.reflection." + "theTypeDescriptionManager" ), + UNO_QUERY_THROW ); + + // The registries are consumed twice, once to insert them into the + // TypeDescriptionManager so that TypeEmitter can work on + // css.star.reflection.XTypeDescription representation, and once + // directly as unoidl::Provider instances to keep track which types are + // coming from the mandatory registries for the "no explicit types + // given" case (which iterates over the full TypeDescriptionManager + // now); a welcome clean-up would be to make TypeEmitter work on + // unoidl::Entity directly like the other codemakers: + css::uno::Reference< container::XSet > xSet( xTDmgr, UNO_QUERY_THROW ); + rtl::Reference unoidlMgr(new unoidl::Manager); + std::vector< rtl::Reference< unoidl::Provider > > unoidlMandatoryProvs; + for (auto& rRegistry : extra_registries) + { + xSet->insert(Any(rRegistry)); + unoidlMgr->addProvider(rRegistry); + } + for (auto& rRegistry : mandatory_registries) + { + xSet->insert(Any(rRegistry)); + rtl::Reference< unoidl::Provider > prov(unoidlMgr->addProvider(rRegistry)); + unoidlMandatoryProvs.push_back(prov); + } + + if (0 == output.getLength()) // no output file specified + { + // if only one rdb has been given, then take rdb name + if (1 == mandatory_registries.size()) + { + output = mandatory_registries[ 0 ]; + output = output.copy( output.lastIndexOf( '/' ) +1 ); + sal_Int32 dot = output.lastIndexOf( '.' ); + if (dot > 0) + output = output.copy( 0, dot ); + } + else + { + output = "cli_unotypes"; + } + } + output = path_make_absolute_file_url( output ); + sal_Int32 slash = output.lastIndexOf( '/' ); + OUString sys_output_dir; + if (FileBase::E_None != FileBase::getSystemPathFromFileURL( + output.copy( 0, slash ), sys_output_dir )) + { + throw RuntimeException( + "cannot get system path from file url " + + output.copy( 0, slash ) ); + } + OUString filename( output.copy( slash +1 ) ); + sal_Int32 dot = filename.lastIndexOf( '.' ); + OUString name( filename ); + if (dot < 0) // has no extension + filename += ".dll"; + else + name = name.copy( 0, dot ); + ::System::String ^ output_dir = ustring_to_String( sys_output_dir ); + ::System::String ^ output_file = ustring_to_String( filename ); + + //Get the key pair for making a strong name + StrongNameKeyPair^ kp = nullptr; + if (keyfile.getLength() > 0) + { + ::System::String ^ sKeyFile = ustring_to_String(keyfile); + try { + System::IO::FileStream^ fs = gcnew System::IO::FileStream( + sKeyFile, System::IO::FileMode::Open, + System::IO::FileAccess::Read, System::IO::FileShare::Read); + kp = gcnew StrongNameKeyPair(fs); + fs->Close(); + } + catch (System::IO::FileNotFoundException ^ ) + { + throw Exception("Could not find the keyfile. Verify the --keyfile argument!", 0); + } + } + else + { + if (g_bVerbose) + { + ::System::Console::Write( + "> no key file specified. Cannot create strong name!\n"); + } + } + // setup assembly info: xxx todo set more? e.g. avoid strong versioning + AssemblyName ^ assembly_name = gcnew AssemblyName(); + assembly_name->CodeBase = output_dir; + assembly_name->Name = gcnew ::System::String( + reinterpret_cast(name.getStr())); + if (kp != nullptr) + assembly_name->KeyPair= kp; + + if (version.getLength() != 0) + { + assembly_name->Version= + gcnew ::System::Version( ustring_to_String( version ) ); + } + + // app domain + ::System::AppDomain ^ current_appdomain = + ::System::AppDomain::CurrentDomain; + +// Weird warning from this statement +// warning C4538: 'cli::array ^' : const/volatile qualifiers on this type are not supported +// Could be a compiler bug, says http://stackoverflow.com/questions/12151060/seemingly-inappropriate-compilation-warning-with-c-cli +#pragma warning (push) +#pragma warning (disable: 4538) + // target assembly + Emit::AssemblyBuilder ^ assembly_builder = + current_appdomain->DefineDynamicAssembly( + assembly_name, Emit::AssemblyBuilderAccess::Save, output_dir ); +#pragma warning (pop) + + if (product.getLength() != 0) + { + cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^> (1); + cli::array< ::System::Object^>^args = gcnew cli::array< ::System::Object^>(1); + params[ 0 ] = ::System::String::typeid; + args[ 0 ] = ustring_to_String( product ); + assembly_builder->SetCustomAttribute( + gcnew Emit::CustomAttributeBuilder( + (AssemblyProductAttribute::typeid)->GetConstructor( + params ), args ) ); + } + if (description.getLength() != 0) + { + cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1); + cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1); + params[ 0 ] = ::System::String::typeid; + args[ 0 ] = ustring_to_String( description ); + assembly_builder->SetCustomAttribute( + gcnew Emit::CustomAttributeBuilder( + (AssemblyDescriptionAttribute::typeid)->GetConstructor( + params ), args ) ); + } + if (company.getLength() != 0) + { + cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1); + cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1); + params[ 0 ] = ::System::String::typeid; + args[ 0 ] = ustring_to_String( company ); + assembly_builder->SetCustomAttribute( + gcnew Emit::CustomAttributeBuilder( + (AssemblyCompanyAttribute::typeid)->GetConstructor( + params ), args ) ); + } + if (copyright.getLength() != 0) + { + cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1); + cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1); + params[ 0 ] = ::System::String::typeid; + args[ 0 ] = ustring_to_String( copyright ); + assembly_builder->SetCustomAttribute( + gcnew Emit::CustomAttributeBuilder( + (AssemblyCopyrightAttribute::typeid)->GetConstructor( + params ), args ) ); + } + if (trademark.getLength() != 0) + { + cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1); + cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1); + params[ 0 ] = ::System::String::typeid; + args[ 0 ] = ustring_to_String( trademark ); + assembly_builder->SetCustomAttribute( + gcnew Emit::CustomAttributeBuilder( + (AssemblyTrademarkAttribute::typeid)->GetConstructor( + params ), args ) ); + } + + // load extra assemblies + cli::array^ assemblies = + gcnew cli::array(extra_assemblies.size()); + for ( size_t pos = 0; pos < extra_assemblies.size(); ++pos ) + { + assemblies[ pos ] = Assembly::LoadFrom( + ustring_to_String( extra_assemblies[ pos ] ) ); + } + + // type emitter + TypeEmitter ^ type_emitter = gcnew TypeEmitter( + assembly_builder->DefineDynamicModule( output_file ), assemblies ); + // add handler resolving assembly's types + ::System::ResolveEventHandler ^ type_resolver = + gcnew ::System::ResolveEventHandler( + type_emitter, &TypeEmitter::type_resolve ); + current_appdomain->TypeResolve += type_resolver; + + // and emit types to it + if (explicit_types.empty()) + { + css::uno::Reference< reflection::XTypeDescriptionEnumeration > xTD_enum( + css::uno::Reference< reflection::XTypeDescriptionEnumerationAccess >( + xTDmgr, UNO_QUERY_THROW ) + ->createTypeDescriptionEnumeration( + OUString() /* all IDL modules */, + Sequence< TypeClass >() /* all classes of types */, + reflection::TypeDescriptionSearchDepth_INFINITE ) ); + while (xTD_enum->hasMoreElements()) + { + css::uno::Reference< reflection::XTypeDescription > td( + xTD_enum->nextTypeDescription()); + OUString name(td->getName()); + bool bEmit = std::any_of(unoidlMandatoryProvs.begin(), unoidlMandatoryProvs.end(), + [&name](rtl::Reference& rProv) { return rProv->findEntity(name).is(); }); + if (bEmit) { + type_emitter->get_type(td); + } + } + } + else + { + for ( size_t nPos = explicit_types.size(); nPos--; ) + { + type_emitter->get_type( + css::uno::Reference< reflection::XTypeDescription >( + xTDmgr->getByHierarchicalName( explicit_types[ nPos ] ), + UNO_QUERY_THROW ) ); + } + } + type_emitter->finish(); + + if (g_bVerbose) + { + ::System::Console::Write( + "> saving assembly {0}{1}{2}...", + output_dir, + gcnew ::System::String( + ::System::IO::Path::DirectorySeparatorChar, 1 ), + output_file ); + } + assembly_builder->Save( output_file ); + if (g_bVerbose) + { + ::System::Console::WriteLine( "ok." ); + } + current_appdomain->TypeResolve -= type_resolver; + } + catch (unoidl::NoSuchFileException & e) + { + std::cerr << "ERROR: No such file <" << e.getUri() << ">\n"; + return EXIT_FAILURE; + } + catch (unoidl::FileFormatException & e) + { + std::cerr + << "ERROR: Bad format of <" << e.getUri() << ">, \"" + << e.getDetail() << "\"\n"; + return EXIT_FAILURE; + } + catch (Exception & exc) + { + OString msg( + OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) ); + fprintf( + stderr, "\n> error: %s\n> dying abnormally...\n", msg.getStr() ); + ret = 1; + } + catch (::System::Exception ^ exc) + { + OString msg( OUStringToOString( + String_to_ustring( exc->ToString() ), + osl_getThreadTextEncoding() ) ); + fprintf( + stderr, + "\n> error: .NET exception occurred: %s\n> dying abnormally...", + msg.getStr() ); + ret = 1; + } + + try + { + css::uno::Reference< lang::XComponent > xComp( xContext, UNO_QUERY ); + if (xComp.is()) + xComp->dispose(); + } + catch (Exception & exc) + { + OString msg( + OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) ); + fprintf( + stderr, + "\n> error disposing component context: %s\n" + "> dying abnormally...\n", + msg.getStr() ); + ret = 1; + } + + return ret; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cli_ure/source/climaker/climaker_emit.cxx b/cli_ure/source/climaker/climaker_emit.cxx new file mode 100644 index 0000000000..4f4dceef9f --- /dev/null +++ b/cli_ure/source/climaker/climaker_emit.cxx @@ -0,0 +1,2279 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "climaker_share.h" + +#include "rtl/string.hxx" +#include "rtl/ustrbuf.hxx" +#include "com/sun/star/reflection/XIndirectTypeDescription.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" +#include + +using namespace ::System::Reflection; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace climaker +{ +System::String^ mapUnoPolymorphicName(System::String^ unoName); + +static inline ::System::String ^ to_cts_name( + OUString const & uno_name ) +{ + return ustring_to_String("unoidl." + uno_name); +} + + +static inline ::System::Object ^ to_cli_constant( Any const & value ) +{ + switch (value.getValueTypeClass()) + { + case TypeClass_CHAR: + return ((::System::Char) *reinterpret_cast< sal_Unicode const * >( + value.getValue() )); + case TypeClass_BOOLEAN: + return ((::System::Boolean) + sal_False != *reinterpret_cast< sal_Bool const * >( + value.getValue() )); + case TypeClass_BYTE: + return ((::System::Byte) *reinterpret_cast< sal_Int8 const * >( + value.getValue() )); + case TypeClass_SHORT: + return ((::System::Int16) *reinterpret_cast< sal_Int16 const * >( + value.getValue() )); + case TypeClass_UNSIGNED_SHORT: + return ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >( + value.getValue() )); + case TypeClass_LONG: + return ((::System::Int32) *reinterpret_cast< sal_Int32 const * >( + value.getValue() )); + case TypeClass_UNSIGNED_LONG: + return ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >( + value.getValue() )); + case TypeClass_HYPER: + return ((::System::Int64) *reinterpret_cast< sal_Int64 const * >( + value.getValue() )); + case TypeClass_UNSIGNED_HYPER: + return ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >( + value.getValue() )); + case TypeClass_FLOAT: + return ((::System::Single) *reinterpret_cast< float const * >( + value.getValue() )); + case TypeClass_DOUBLE: + return ((::System::Double) *reinterpret_cast< double const * >( + value.getValue() )); + default: + throw RuntimeException( + "unexpected constant type " + + value.getValueType().getTypeName() ); + } +} + + +static inline void emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index ) +{ + switch (index) + { + case 0: +#pragma warning (push) +#pragma warning (disable: 4538) // const/volatile qualifiers on this type are not supported + code->Emit( Emit::OpCodes::Ldarg_0 ); +#pragma warning (pop) + break; + case 1: + code->Emit( Emit::OpCodes::Ldarg_1 ); + break; + case 2: + code->Emit( Emit::OpCodes::Ldarg_2 ); + break; + case 3: + code->Emit( Emit::OpCodes::Ldarg_3 ); + break; + default: + if (index < 0x100) + code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index ); + else if (index < 0x8000) + code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index ); + else + code->Emit( Emit::OpCodes::Ldarg, index ); + break; + } +} + +void polymorphicStructNameToStructName(::System::String ^* sPolyName) +{ + if ((*sPolyName)->EndsWith(">") == false) + return; + + int index = (*sPolyName)->IndexOf('<'); + OSL_ASSERT(index != -1); + *sPolyName = (*sPolyName)->Substring(0, index); +} + + +System::String^ mapUnoTypeName(System::String ^ typeName) +{ + ::System::Text::StringBuilder^ buf= gcnew System::Text::StringBuilder(); + ::System::String ^ sUnoName = ::System::String::Copy(typeName); + //determine if the type is a sequence and its dimensions + int dims= 0; + if (typeName->StartsWith("["))//if (usUnoName[0] == '[') + { + int index= 1; + while (true) + { + if (typeName[index++] == ']')//if (usUnoName[index++] == ']') + dims++; + if (typeName[index++] != '[')//usUnoName[index++] != '[') + break; + } + sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1); + } + if (sUnoName->Equals(const_cast(Constants::sUnoBool))) + buf->Append(const_cast(Constants::sBoolean)); + else if (sUnoName->Equals(const_cast(Constants::sUnoChar))) + buf->Append(const_cast(Constants::sChar)); + else if (sUnoName->Equals(const_cast(Constants::sUnoByte))) + buf->Append(const_cast(Constants::sByte)); + else if (sUnoName->Equals(const_cast(Constants::sUnoShort))) + buf->Append(const_cast(Constants::sInt16)); + else if (sUnoName->Equals(const_cast(Constants::sUnoUShort))) + buf->Append(const_cast(Constants::sUInt16)); + else if (sUnoName->Equals(const_cast(Constants::sUnoLong))) + buf->Append(const_cast(Constants::sInt32)); + else if (sUnoName->Equals(const_cast(Constants::sUnoULong))) + buf->Append(const_cast(Constants::sUInt32)); + else if (sUnoName->Equals(const_cast(Constants::sUnoHyper))) + buf->Append(const_cast(Constants::sInt64)); + else if (sUnoName->Equals(const_cast(Constants::sUnoUHyper))) + buf->Append(const_cast(Constants::sUInt64)); + else if (sUnoName->Equals(const_cast(Constants::sUnoFloat))) + buf->Append(const_cast(Constants::sSingle)); + else if (sUnoName->Equals(const_cast(Constants::sUnoDouble))) + buf->Append(const_cast(Constants::sDouble)); + else if (sUnoName->Equals(const_cast(Constants::sUnoString))) + buf->Append(const_cast(Constants::sString)); + else if (sUnoName->Equals(const_cast(Constants::sUnoVoid))) + buf->Append(const_cast(Constants::sVoid)); + else if (sUnoName->Equals(const_cast(Constants::sUnoType))) + buf->Append(const_cast(Constants::sType)); + else if (sUnoName->Equals(const_cast(Constants::sUnoXInterface))) + buf->Append(const_cast(Constants::sObject)); + else if (sUnoName->Equals(const_cast(Constants::sUnoAny))) + { + buf->Append(const_cast(Constants::sAny)); + } + else + { + //put "unoidl." at the beginning + buf->Append(const_cast(Constants::sUnoidl)); + buf->Append(mapUnoPolymorphicName(sUnoName)); + } + // append [] + for (;dims--;) + buf->Append(const_cast(Constants::sBrackets)); + + return buf->ToString(); +} + + +/** For example, there is a uno type + com.sun.star.Foo. + The values in the type list + are uno types and are replaced by cli types, such as System.Char, + System.Int32, etc. + + Strings can be as complicated as this + test.MyStruct> + */ +System::String^ mapUnoPolymorphicName(System::String^ unoName) +{ + int index = unoName->IndexOf('<'); + if (index == -1) + return unoName; + + System::Text::StringBuilder ^ builder = + gcnew System::Text::StringBuilder(unoName->Substring(0, index +1 )); + + //Find the first occurrence of ',' + //If the parameter is a polymorphic struct then we need to ignore everything + //between the brackets because it can also contain commas + //get the type list within < and > + int endIndex = unoName->Length - 1; + index++; + int cur = index; + int countParams = 0; + while (cur <= endIndex) + { + System::Char c = unoName[cur]; + if (c == ',' || c == '>') + { + //insert a comma if needed + if (countParams != 0) + builder->Append(","); + countParams++; + System::String ^ sParam = unoName->Substring(index, cur - index); + //skip the comma + cur++; + //the index to the beginning of the next param + index = cur; + builder->Append(mapUnoTypeName(sParam)); + } + else if (c == '<') + { + cur++; + //continue until the matching '>' + int numNested = 0; + for (;;cur++) + { + System::Char curChar = unoName[cur]; + if (curChar == '<') + { + numNested ++; + } + else if (curChar == '>') + { + if (numNested > 0) + numNested--; + else + break; + } + } + } + cur++; + } + + builder->Append((System::Char) '>'); + return builder->ToString(); +} + + +Assembly ^ TypeEmitter::type_resolve( + ::System::Object ^, ::System::ResolveEventArgs ^ args ) +{ + ::System::String ^ cts_name = args->Name; + ::System::Type ^ ret_type = nullptr; + + iface_entry ^ entry = dynamic_cast< iface_entry ^ >(m_incomplete_ifaces[cts_name] ); + if (nullptr != entry) + ret_type = entry->m_type_builder; + + if (nullptr == ret_type) + { + sal_Int32 len = m_extra_assemblies->Length; + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + ret_type = m_extra_assemblies[ pos ]->GetType( + cts_name, false /* no exc */ ); + if (nullptr != ret_type) + { + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> resolving type {0} from {1}.", + cts_name, ret_type->Assembly->FullName ); + } + break; + } + } + } + if (nullptr != ret_type) + return ret_type->Assembly; + return nullptr; +} + + +::System::Type ^ TypeEmitter::get_type( + ::System::String ^ cts_name, bool throw_exc ) +{ + ::System::Type ^ ret_type = m_module_builder->GetType( cts_name, false ); + //We get the type from the ModuleBuilder even if the type is not complete + //but have been defined. + //if (ret_type == 0) + //{ + // iface_entry * entry = dynamic_cast< iface_entry * >( + // m_incomplete_ifaces->get_Item( cts_name ) ); + // if (0 != entry) + // ret_type = entry->m_type_builder; + //} + //try the cli_basetypes assembly + if (ret_type == nullptr) + { + ::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name); + builder->Append(",cli_basetypes"); + ret_type = ::System::Type::GetType(builder->ToString()); + } + + if (ret_type == nullptr) + { + try + { + // may call on type_resolve() + return ::System::Type::GetType( cts_name, throw_exc ); + } + catch (::System::Exception^ exc) + { + //If the type is not found one may have forgotten to specify assemblies with + //additional types + ::System::Text::StringBuilder ^ sb = gcnew ::System::Text::StringBuilder(); + sb->Append(gcnew ::System::String("\nThe type ")); + sb->Append(cts_name); + sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to " + "specify an additional assembly with the --reference option?\n")); + if (throw_exc) + throw gcnew ::System::Exception(sb->ToString(), exc); + } + } + else + { + return ret_type; + } +} + + +::System::Type ^ TypeEmitter::get_type_Exception() +{ + if (nullptr == m_type_Exception) + { + m_type_Exception = get_type( + "unoidl.com.sun.star.uno.Exception", false /* no exc */ ); + if (nullptr == m_type_Exception) + { + // define hardcoded type unoidl.com.sun.star.uno.Exception + Emit::TypeBuilder ^ type_builder = + m_module_builder->DefineType( + "unoidl.com.sun.star.uno.Exception", + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass), + (::System::Exception::typeid) ); + Emit::FieldBuilder ^ field_Context = type_builder->DefineField( + "Context", (::System::Object::typeid), + FieldAttributes::Public ); + // default .ctor + type_builder->DefineDefaultConstructor( c_ctor_method_attr ); + // .ctor + array< ::System::Type^>^ param_types = + gcnew array< ::System::Type^>(2); + param_types[ 0 ] = ::System::String::typeid; + param_types[ 1 ] = ::System::Object::typeid; + Emit::ConstructorBuilder ^ ctor_builder = + type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, + param_types ); + ctor_builder->DefineParameter( + 1, ParameterAttributes::In, "Message" ); + ctor_builder->DefineParameter( + 2, ParameterAttributes::In, "Context" ); + Emit::ILGenerator ^ code = ctor_builder->GetILGenerator(); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldarg_1 ); + param_types = gcnew array< ::System::Type^>(1); + param_types[ 0 ] = ::System::String::typeid; + code->Emit( + Emit::OpCodes::Call, + (::System::Exception::typeid) + ->GetConstructor( param_types ) ); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldarg_2 ); + code->Emit( Emit::OpCodes::Stfld, field_Context ); + code->Emit( Emit::OpCodes::Ret ); + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting exception type " + "unoidl.com.sun.star.uno.Exception" ); + } + m_type_Exception = type_builder->CreateType(); + } + } + return m_type_Exception; +} + + +::System::Type ^ TypeEmitter::get_type_RuntimeException() +{ + if (nullptr == m_type_RuntimeException) + { + m_type_RuntimeException = get_type( + "unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ ); + if (nullptr == m_type_RuntimeException) + { + // define hardcoded type unoidl.com.sun.star.uno.RuntimeException + ::System::Type ^ type_Exception = get_type_Exception(); + Emit::TypeBuilder ^ type_builder = + m_module_builder->DefineType( + "unoidl.com.sun.star.uno.RuntimeException", + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass), + type_Exception ); + // default .ctor + type_builder->DefineDefaultConstructor( c_ctor_method_attr ); + // .ctor + array< ::System::Type^>^ param_types = + gcnew array< ::System::Type^>(2); + param_types[ 0 ] = ::System::String::typeid; + param_types[ 1 ] = ::System::Object::typeid; + Emit::ConstructorBuilder ^ ctor_builder = + type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, + param_types ); + ctor_builder->DefineParameter( + 1, ParameterAttributes::In, "Message" ); + ctor_builder->DefineParameter( + 2, ParameterAttributes::In, "Context" ); + Emit::ILGenerator ^ code = ctor_builder->GetILGenerator(); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldarg_1 ); + code->Emit( Emit::OpCodes::Ldarg_2 ); + code->Emit( + Emit::OpCodes::Call, + type_Exception->GetConstructor( param_types ) ); + code->Emit( Emit::OpCodes::Ret ); + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting exception type " + "unoidl.com.sun.star.uno.RuntimeException" ); + } + m_type_RuntimeException = type_builder->CreateType(); + } + } + return m_type_RuntimeException; +} + + +::System::Type ^ TypeEmitter::get_type( + Reference< reflection::XConstantTypeDescription > const & xType ) +{ + ::System::String ^ cts_name = to_cts_name( xType->getName() ); + ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ ); + if (nullptr == ret_type) + { + Reference< reflection::XConstantTypeDescription > xConstant( + xType, UNO_SET_THROW ); + ::System::Object ^ constant = + to_cli_constant( xConstant->getConstantValue() ); + Emit::TypeBuilder ^ type_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass) ); + + Emit::FieldBuilder ^ field_builder = type_builder->DefineField( + cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ), + constant->GetType(), + (FieldAttributes) (FieldAttributes::Public | + FieldAttributes::Static | + FieldAttributes::Literal) ); + field_builder->SetConstant( constant ); + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting constant type {0}", cts_name ); + } + ret_type = type_builder->CreateType(); + } + return ret_type; +} + + +::System::Type ^ TypeEmitter::get_type( + Reference< reflection::XConstantsTypeDescription > const & xType ) +{ + ::System::String ^ cts_name = to_cts_name( xType->getName() ); + ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ ); + if (nullptr == ret_type) + { + Emit::TypeBuilder ^ type_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass) ); + + Sequence< Reference< + reflection::XConstantTypeDescription > > seq_constants( + xType->getConstants() ); + Reference< reflection::XConstantTypeDescription > const * constants = + seq_constants.getConstArray(); + sal_Int32 constants_length = seq_constants.getLength(); + for ( sal_Int32 constants_pos = 0; + constants_pos < constants_length; ++constants_pos ) + { + Reference< + reflection::XConstantTypeDescription > const & xConstant = + constants[ constants_pos ]; + ::System::Object ^ constant = + to_cli_constant( xConstant->getConstantValue() ); + ::System::String ^ uno_name = + ustring_to_String( xConstant->getName() ); + Emit::FieldBuilder ^ field_builder = type_builder->DefineField( + uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ), + constant->GetType(), + (FieldAttributes) (FieldAttributes::Public | + FieldAttributes::Static | + FieldAttributes::Literal) ); + field_builder->SetConstant( constant ); + } + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting constants group type {0}", cts_name ); + } + ret_type = type_builder->CreateType(); + } + return ret_type; +} + + +::System::Type ^ TypeEmitter::get_type( + Reference< reflection::XEnumTypeDescription > const & xType ) +{ + ::System::String ^ cts_name = to_cts_name( xType->getName() ); + ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ ); + if (nullptr == ret_type) + { + // workaround enum builder bug + Emit::TypeBuilder ^ enum_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed), + ::System::Enum::typeid ); + enum_builder->DefineField( + "value__", ::System::Int32::typeid, + (FieldAttributes) (FieldAttributes::Private | + FieldAttributes::SpecialName | + FieldAttributes::RTSpecialName) ); + Sequence< OUString > seq_enum_names( xType->getEnumNames() ); + Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() ); + sal_Int32 enum_length = seq_enum_names.getLength(); + OSL_ASSERT( enum_length == seq_enum_values.getLength() ); + OUString const * enum_names = seq_enum_names.getConstArray(); + sal_Int32 const * enum_values = seq_enum_values.getConstArray(); + for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos ) + { +// enum_builder->DefineLiteral( +// ustring_to_String( enum_names[ enum_pos ] ), +// __box ((::System::Int32) enum_values[ enum_pos ]) ); + Emit::FieldBuilder ^ field_builder = + enum_builder->DefineField( + ustring_to_String( enum_names[ enum_pos ] ), + enum_builder, + (FieldAttributes) (FieldAttributes::Public | + FieldAttributes::Static | + FieldAttributes::Literal) ); + field_builder->SetConstant( + ((::System::Int32) enum_values[ enum_pos ]) ); + } + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting enum type {0}", cts_name ); + } + ret_type = enum_builder->CreateType(); + } + return ret_type; +} + + +::System::Type ^ TypeEmitter::get_type( + Reference< reflection::XCompoundTypeDescription > const & xType ) +{ + OUString uno_name( xType->getName() ); + if (TypeClass_EXCEPTION == xType->getTypeClass()) + { + if ( uno_name == "com.sun.star.uno.Exception" ) + { + return get_type_Exception(); + } + if ( uno_name == "com.sun.star.uno.RuntimeException" ) + { + return get_type_RuntimeException(); + } + } + ::System::String ^ cts_name = to_cts_name( uno_name ); + // if the struct is an instantiated polymorphic struct then we create the simple struct name + // For example: + // void func ([in] PolyStruct arg); + //PolyStruct will be converted to PolyStruct + polymorphicStructNameToStructName( & cts_name); + + ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ ); + if (nullptr == ret_type) + { + Reference< reflection::XCompoundTypeDescription > xBaseType( + xType->getBaseType(), UNO_QUERY ); + ::System::Type ^ base_type = (xBaseType.is() + ? get_type( xBaseType ) + : ::System::Object::typeid); + Emit::TypeBuilder ^ type_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass), + base_type ); + + + // insert to be completed + struct_entry ^ entry = gcnew struct_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + entry->m_base_type = base_type; + m_incomplete_structs->Add( cts_name, entry ); + + // type is incomplete + ret_type = type_builder; + } + + //In case of an instantiated polymorphic struct we want to return a + //uno.PolymorphicType (inherits Type) rather than Type. This is needed for constructing + //the service code. We can only do that if the struct is completed. + if (m_generated_structs[cts_name]) + { + Reference< reflection::XStructTypeDescription> xStructTypeDesc( + xType, UNO_QUERY); + + if (xStructTypeDesc.is()) + { + Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments(); + sal_Int32 numTypes = seqTypeArgs.getLength(); + if (numTypes > 0) + { + //it is an instantiated polymorphic struct + ::System::String ^ sCliName = mapUnoTypeName(ustring_to_String(xType->getName())); + ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName); + } + } + } + return ret_type; +} + + +::System::Type ^ TypeEmitter::get_type( + Reference< reflection::XInterfaceTypeDescription2 > const & xType ) +{ + OUString uno_name( xType->getName() ); + if ( uno_name == "com.sun.star.uno.XInterface" ) + { + return ::System::Object::typeid; + } + + ::System::String ^ cts_name = to_cts_name( xType->getName() ); + ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ ); + if (nullptr == ret_type) + { + Emit::TypeBuilder ^ type_builder; + + TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Interface | + TypeAttributes::Abstract | + TypeAttributes::AnsiClass); + + std::vector > vecBaseTypes; + Sequence > seqBaseTypes = + xType->getBaseTypes(); + if (seqBaseTypes.getLength() > 0) + { + for (int i = 0; i < seqBaseTypes.getLength(); i++) + { + Reference xIfaceTd = + resolveInterfaceTypedef(seqBaseTypes[i]); + + if ( xIfaceTd->getName() != "com.sun.star.uno.XInterface" ) + { + vecBaseTypes.push_back(xIfaceTd); + } + } + + array< ::System::Type^>^ base_interfaces = + gcnew array< ::System::Type^>( vecBaseTypes.size() ); + + int index = 0; + for (auto const & vecBaseType : vecBaseTypes) + { + base_interfaces[ index ] = get_type( vecBaseType ); + ++index; + } + type_builder = m_module_builder->DefineType( + cts_name, attr, nullptr, base_interfaces ); + } + else + { + ::System::Console::WriteLine( + "warning: IDL interface {0} is not derived from " + "com.sun.star.uno.XInterface!", + ustring_to_String( uno_name ) ); + + type_builder = m_module_builder->DefineType( cts_name, attr ); + } + + // insert to be completed + iface_entry ^ entry = gcnew iface_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + m_incomplete_ifaces->Add( cts_name, entry ); + + // type is incomplete + ret_type = type_builder; + } + return ret_type; +} + + +::System::Type ^ TypeEmitter::get_type( + Reference< reflection::XServiceTypeDescription2 > const & xType ) +{ + if (xType->isSingleInterfaceBased() == sal_False) + return nullptr; + + System::String ^ cts_name = to_cts_name( xType->getName() ); + System::Type ^ ret_type = get_type( cts_name, false /* no exc */ ); + if (ret_type != nullptr) + return ret_type; + + TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass); + + Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType( + cts_name, attr); + + // insert to be completed + service_entry ^ entry = gcnew service_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + m_incomplete_services->Add(cts_name,entry ); + + return type_builder; +} + +::System::Type ^ TypeEmitter::get_type( + Reference const & xType ) +{ + if (xType->isInterfaceBased() == sal_False) + return nullptr; + + ::System::String^ cts_name = to_cts_name( xType->getName() ); + ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ ); + if (ret_type != nullptr) + return ret_type; + + TypeAttributes attr = static_cast( + TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass); + + Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType( + cts_name, attr); + + // insert to be completed + singleton_entry ^ entry = gcnew singleton_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + m_incomplete_singletons->Add(cts_name,entry ); + + return type_builder; + +} + + +::System::Type ^ TypeEmitter::complete_iface_type( iface_entry ^ entry ) +{ + Emit::TypeBuilder ^ type_builder = entry->m_type_builder; + reflection::XInterfaceTypeDescription2 * xType = entry->m_xType; + + Sequence > seqBaseTypes( xType->getBaseTypes() ); + if (seqBaseTypes.getLength() > 0) + { + for (int i = 0; i < seqBaseTypes.getLength(); i++) + { + //make sure we get the interface rather than a typedef + Reference aBaseType = + resolveInterfaceTypedef( seqBaseTypes[i]); + + if ( aBaseType->getName() != "com.sun.star.uno.XInterface" ) + { + ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() ); + iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >( + m_incomplete_ifaces[basetype_name] ); + if (nullptr != base_entry) + { + // complete uncompleted base type first + complete_iface_type( base_entry ); + } + } + } + } + + Sequence< + Reference< reflection::XInterfaceMemberTypeDescription > > seq_members( + xType->getMembers() ); + Reference< reflection::XInterfaceMemberTypeDescription > const * members = + seq_members.getConstArray(); + sal_Int32 members_length = seq_members.getLength(); + for ( sal_Int32 members_pos = 0; + members_pos < members_length; ++members_pos ) + { + Reference< + reflection::XInterfaceMemberTypeDescription > const & xMember = + members[ members_pos ]; + Sequence< Reference< reflection::XTypeDescription > > seq_exceptions; + Emit::MethodBuilder ^ method_builder; + + MethodAttributes c_method_attr = (MethodAttributes) + (MethodAttributes::Public | + MethodAttributes::Abstract | + MethodAttributes::Virtual | + MethodAttributes::NewSlot | + MethodAttributes::HideBySig); + + if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass()) + { + Reference< reflection::XInterfaceMethodTypeDescription > xMethod( + xMember, UNO_QUERY_THROW ); + + Sequence< + Reference< reflection::XMethodParameter > > seq_parameters( + xMethod->getParameters() ); + sal_Int32 params_length = seq_parameters.getLength(); + array< ::System::Type^>^ param_types = + gcnew array< ::System::Type^>( params_length ); + Reference< reflection::XMethodParameter > const * parameters = + seq_parameters.getConstArray(); + // first determine all types + //Make the first param type as return type + sal_Int32 params_pos = 0; + for ( ; params_pos < params_length; ++params_pos ) + { + Reference< reflection::XMethodParameter > const & xParam = + parameters[ params_pos ]; + ::System::Type ^ param_type = get_type( xParam->getType() ); + ::System::String ^ param_type_name = param_type->FullName; + if (xParam->isOut()) + { + param_type = get_type( + ::System::String::Concat( + param_type_name, "&" ), true ); + } + param_types[ xParam->getPosition() ] = param_type; + } + + + // create method +// if (tb) +// method_builder = type_builder->DefineMethod( +// ustring_to_String( xMethod->getMemberName() ), +// c_method_attr, tb, +// param_types ); +// else + method_builder = type_builder->DefineMethod( + ustring_to_String( xMethod->getMemberName() ), + c_method_attr, get_type( xMethod->getReturnType() ), + param_types ); + // then define parameter infos + params_pos = 0; + for ( ; params_pos < params_length; ++params_pos ) + { + Reference< reflection::XMethodParameter > const & xParam = + parameters[ params_pos ]; + long param_flags = 0; + if (xParam->isIn()) + param_flags |= (long)ParameterAttributes::In; + if (xParam->isOut()) + param_flags |= (long)ParameterAttributes::Out; + OSL_ASSERT( 0 != param_flags ); + method_builder->DefineParameter( + xParam->getPosition() +1 /* starts with 1 */, + (ParameterAttributes) param_flags, + ustring_to_String( xParam->getName() ) ); + } + //Apply attribute TypeParametersAttribute to return value if it + //is a parameterized Type. Currently only structs can have parameters. + Reference xReturnStruct( + xMethod->getReturnType(), UNO_QUERY); + + if (xReturnStruct.is()) + { + Sequence > seq_type_args = + xReturnStruct->getTypeArguments(); + if (seq_type_args.getLength() != 0) + { + //get th ctor of the attribute + array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")}; + //Get the arguments for the attribute's ctor + Reference const * arXTypeArgs = + seq_type_args.getConstArray(); + int numTypes = seq_type_args.getLength(); + array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes); + for (int i = 0; i < numTypes; i++) + arCtsTypes[i] = get_type(arXTypeArgs[i]); + array< ::System::Object^>^ arArgs = {arCtsTypes}; + + Emit::CustomAttributeBuilder ^ attrBuilder = + gcnew Emit::CustomAttributeBuilder( + ::uno::TypeArgumentsAttribute::typeid + ->GetConstructor( arCtor), + arArgs); + + method_builder->SetCustomAttribute(attrBuilder); + } + } + + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder^ attrBuilder = + get_iface_method_exception_attribute(xMethod); + if (attrBuilder != nullptr) + method_builder->SetCustomAttribute(attrBuilder); + + // oneway attribute + if (xMethod->isOneway()) + { + array< ::System::Type^>^ arCtorOneway = gcnew array< ::System::Type^>(0); + array< ::System::Object^>^ arArgs = gcnew array< ::System::Object^>(0); + Emit::CustomAttributeBuilder ^ attrBuilder = + gcnew Emit::CustomAttributeBuilder( + ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway), + arArgs); + method_builder->SetCustomAttribute(attrBuilder); + } + } + else // attribute + { + OSL_ASSERT( + TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() ); + Reference< + reflection::XInterfaceAttributeTypeDescription2 > xAttribute( + xMember, UNO_QUERY_THROW ); + + MethodAttributes c_property_method_attr = (MethodAttributes) + (c_method_attr | MethodAttributes::SpecialName); + + ::System::Type ^ attribute_type = get_type( xAttribute->getType() ); + array< ::System::Type^>^ parameters = + gcnew array< ::System::Type^> ( 0 ); + + Emit::PropertyBuilder ^ property_builder = + type_builder->DefineProperty( + ustring_to_String( xAttribute->getMemberName() ), + PropertyAttributes::None, + attribute_type, parameters ); + + //set BoundAttribute, if necessary + if (xAttribute->isBound()) + { + ConstructorInfo ^ ctorBoundAttr = + ::uno::BoundAttribute::typeid->GetConstructor( + gcnew array(0)); + Emit::CustomAttributeBuilder ^ attrBuilderBound = + gcnew Emit::CustomAttributeBuilder( + ctorBoundAttr, gcnew array< ::System::Object^>(0)); + property_builder->SetCustomAttribute(attrBuilderBound); + } + + // getter + Emit::MethodBuilder ^ method_builder = + type_builder->DefineMethod( + ustring_to_String( "get_" + + xAttribute->getMemberName() ), + c_property_method_attr, attribute_type, parameters ); + + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder^ attrBuilder = + get_exception_attribute(xAttribute->getGetExceptions()); + if (attrBuilder != nullptr) + method_builder->SetCustomAttribute(attrBuilder); + + property_builder->SetGetMethod( method_builder ); + + if (! xAttribute->isReadOnly()) + { + // setter + parameters = gcnew array< ::System::Type^> ( 1 ); + parameters[ 0 ] = attribute_type; + method_builder = + type_builder->DefineMethod( + ustring_to_String( "set_" + + xAttribute->getMemberName() ), + c_property_method_attr, nullptr, parameters ); + // define parameter info + method_builder->DefineParameter( + 1 /* starts with 1 */, ParameterAttributes::In, "value" ); + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder^ attrBuilder = + get_exception_attribute(xAttribute->getSetExceptions()); + if (attrBuilder != nullptr) + method_builder->SetCustomAttribute(attrBuilder); + + property_builder->SetSetMethod( method_builder ); + } + } + } + + // remove from incomplete types map + ::System::String ^ cts_name = type_builder->FullName; + m_incomplete_ifaces->Remove( cts_name ); + xType->release(); + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting interface type {0}", cts_name ); + } + return type_builder->CreateType(); +} + +::System::Type ^ TypeEmitter::complete_struct_type( struct_entry ^ entry ) +{ + OSL_ASSERT(entry); + ::System::String ^ cts_name = entry->m_type_builder->FullName; + + //Polymorphic struct, define uno.TypeParametersAttribute + //A polymorphic struct cannot have a basetype. + //When we create the template of the struct then we have no exact types + //and the name does not contain a parameter list + Sequence< OUString > seq_type_parameters; + Reference< reflection::XStructTypeDescription> xStructTypeDesc( + entry->m_xType, UNO_QUERY); + if (xStructTypeDesc.is()) + { + seq_type_parameters = xStructTypeDesc->getTypeParameters(); + int numTypes = 0; + if ((numTypes = seq_type_parameters.getLength()) > 0) + { + array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes); + for (int i = 0; i < numTypes; i++) + aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]); + array< ::System::Object^>^ args = {aArg}; + + array< ::System::Type^>^ arTypesCtor = + {::System::Type::GetType("System.String[]")}; + Emit::CustomAttributeBuilder ^ attrBuilder = + gcnew Emit::CustomAttributeBuilder( + ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor), + args); + entry->m_type_builder->SetCustomAttribute(attrBuilder); + } + } + + // optional: lookup base type whether generated entry of this session + struct_entry ^ base_type_entry = nullptr; + if (nullptr != entry->m_base_type) + { + //ToDo maybe get from incomplete structs + base_type_entry = + dynamic_cast< struct_entry ^ >( + m_generated_structs[ + entry->m_base_type->FullName ] ); + } + + // members + Sequence< Reference< reflection::XTypeDescription > > seq_members( + entry->m_xType->getMemberTypes() ); + Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() ); + sal_Int32 members_length = seq_members.getLength(); + OSL_ASSERT( seq_member_names.getLength() == members_length ); + //check if we have a XTypeDescription for every member. If not then the user may + //have forgotten to specify additional rdbs with the --extra option. + Reference< reflection::XTypeDescription > const * pseq_members = + seq_members.getConstArray(); + OUString const * pseq_member_names = + seq_member_names.getConstArray(); + for (int i = 0; i < members_length; i++) + { + const OUString sType(entry->m_xType->getName()); + const OUString sMemberName(pseq_member_names[i]); + if ( ! pseq_members[i].is()) + throw RuntimeException("Missing type description . Check if you need to " + "specify additional RDBs with the --extra option. Type missing for: " + sType + + "::" + sMemberName,0); + } + + sal_Int32 all_members_length = 0; + sal_Int32 member_pos; + sal_Int32 type_param_pos = 0; + + // collect base types; wrong order + ::System::Collections::ArrayList ^ base_types_list = + gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ ); + for (::System::Type ^ base_type_pos = entry->m_base_type; + ! base_type_pos->Equals( ::System::Object::typeid ); + base_type_pos = base_type_pos->BaseType ) + { + base_types_list->Add( base_type_pos ); + if (base_type_pos->Equals( ::System::Exception::typeid )) + { + // special Message member + all_members_length += 1; + break; // don't include System.Exception base classes + } + else + { + //ensure the base type is complete. Otherwise GetFields won't work + get_complete_struct(base_type_pos->FullName); + all_members_length += + base_type_pos->GetFields( + (BindingFlags) (BindingFlags::Instance | + BindingFlags::Public | + BindingFlags::DeclaredOnly) ) + ->Length; + } + } + + // create all_members arrays; right order + array< ::System::String^>^ all_member_names = + gcnew array< ::System::String^> (all_members_length + members_length ); + array< ::System::Type^>^ all_param_types = + gcnew array< ::System::Type^> (all_members_length + members_length ); + member_pos = 0; + for ( sal_Int32 pos = base_types_list->Count; pos--; ) + { + ::System::Type ^ base_type = safe_cast< ::System::Type ^ >( + base_types_list[pos] ); + if (base_type->Equals( ::System::Exception::typeid )) + { + all_member_names[ member_pos ] = "Message"; + all_param_types[ member_pos ] = ::System::String::typeid; + ++member_pos; + } + else + { + ::System::String ^ base_type_name = base_type->FullName; + + //ToDo m_generated_structs? + struct_entry ^ entry = + dynamic_cast< struct_entry ^ >( + m_generated_structs[base_type_name] ); + if (nullptr == entry) + { + // complete type + array^ fields = + base_type->GetFields( + (BindingFlags) (BindingFlags::Instance | + BindingFlags::Public | + BindingFlags::DeclaredOnly) ); + sal_Int32 len = fields->Length; + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + FieldInfo ^ field = fields[ pos ]; + all_member_names[ member_pos ] = field->Name; + all_param_types[ member_pos ] = field->FieldType; + ++member_pos; + } + } + else // generated during this session: + // members may be incomplete ifaces + { + sal_Int32 len = entry->m_member_names->Length; + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + all_member_names[ member_pos ] = + entry->m_member_names[ pos ]; + all_param_types[ member_pos ] = + entry->m_param_types[ pos ]; + ++member_pos; + } + } + } + } + OSL_ASSERT( all_members_length == member_pos ); + + // build up entry +// struct_entry * entry = new struct_entry(); + entry->m_member_names = gcnew array< ::System::String^> ( members_length ); + entry->m_param_types = gcnew array< ::System::Type^> ( members_length ); + + // add members + array^ members = gcnew array ( members_length ); + //Reference< reflection::XTypeDescription > const * pseq_members = + // seq_members.getConstArray(); + //OUString const * pseq_member_names = + // seq_member_names.getConstArray(); + + int curParamIndex = 0; //count the fields which have parameterized types + for ( member_pos = 0; member_pos < members_length; ++member_pos ) + { + ::System::String ^ field_name = + ustring_to_String( pseq_member_names[ member_pos ] ); + ::System::Type ^ field_type; + //Special handling of struct parameter types + bool bParameterizedType = false; + if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN) + { + bParameterizedType = true; + if (type_param_pos < seq_type_parameters.getLength()) + { + field_type = ::System::Object::typeid; + type_param_pos++; + } + else + { + throw RuntimeException( + "unexpected member type in " + entry->m_xType->getName() ); + } + } + else + { + field_type = get_type( pseq_members[ member_pos ] ); + + if (field_type->IsArray + && m_incomplete_structs[cts_name] + && !field_type->Namespace->Equals("System")) + { + //Find the value type. In case of sequence > find the actual value type + ::System::Type ^ value = field_type; + while ((value = value->GetElementType())->IsArray); + //If the value type is a struct then make sure it is fully created. + get_complete_struct(value->FullName); + field_type = get_type(pseq_members[member_pos]); + } + } + members[ member_pos ] = + entry->m_type_builder->DefineField( + field_name, field_type, FieldAttributes::Public ); + + //parameterized type (polymorphic struct) ? + if (bParameterizedType && xStructTypeDesc.is()) + { + //get the name + OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex); + ::System::String^ sTypeName = ustring_to_String( + seq_type_parameters.getConstArray()[curParamIndex++]); + array< ::System::Object^>^ args = {sTypeName}; + //set ParameterizedTypeAttribute + array< ::System::Type^>^ arCtorTypes = {::System::String::typeid}; + + Emit::CustomAttributeBuilder ^ attrBuilder = + gcnew Emit::CustomAttributeBuilder( + ::uno::ParameterizedTypeAttribute::typeid + ->GetConstructor(arCtorTypes), + args); + + members[member_pos]->SetCustomAttribute(attrBuilder); + } + // add to all_members + all_member_names[ all_members_length + member_pos ] = field_name; + all_param_types[ all_members_length + member_pos ] = field_type; + // add to entry + entry->m_member_names[ member_pos ] = field_name; + entry->m_param_types[ member_pos ] = field_type; + } + all_members_length += members_length; + + // default .ctor + Emit::ConstructorBuilder ^ ctor_builder = + entry->m_type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, + gcnew array< ::System::Type^> ( 0 ) ); + Emit::ILGenerator ^ code = ctor_builder->GetILGenerator(); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( + Emit::OpCodes::Call, + nullptr == base_type_entry + ? entry->m_base_type->GetConstructor( gcnew array< ::System::Type^> ( 0 ) ) + : base_type_entry->m_default_ctor ); + // default initialize members + for ( member_pos = 0; member_pos < members_length; ++member_pos ) + { + FieldInfo ^ field = members[ member_pos ]; + ::System::Type ^ field_type = field->FieldType; + // ::System::Type * new_field_type = m_module_builder->GetType(field_type->FullName, false); + // default initialize: + // string, type, enum, sequence, struct, exception, any + if (field_type->Equals( ::System::String::typeid )) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldstr, "" ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + else if (field_type->Equals( ::System::Type::typeid )) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( + Emit::OpCodes::Ldtoken, ::System::Void::typeid ); + code->Emit( + Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + else if (field_type->IsArray) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldc_I4_0 ); + code->Emit( + Emit::OpCodes::Newarr, field_type->GetElementType() ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + else if (field_type->IsValueType) + { + if (field_type->FullName->Equals( "uno.Any" )) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID")); + code->Emit( Emit::OpCodes::Stfld, field ); + } + } + else if (field_type->IsClass) + { + /* may be XInterface */ + if (! field_type->Equals( ::System::Object::typeid )) + { + // struct, exception + //make sure the struct is already complete. + get_complete_struct(field_type->FullName); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( + Emit::OpCodes::Newobj, + //GetConstructor requires that the member types of the object which is to be constructed are already known. + field_type->GetConstructor( + gcnew array< ::System::Type^> ( 0 ) ) ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + } + } + code->Emit( Emit::OpCodes::Ret ); + entry->m_default_ctor = ctor_builder; + + // parameterized .ctor including all base members + ctor_builder = entry->m_type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, all_param_types ); + for ( member_pos = 0; member_pos < all_members_length; ++member_pos ) + { + ctor_builder->DefineParameter( + member_pos +1 /* starts with 1 */, ParameterAttributes::In, + all_member_names[ member_pos ] ); + } + code = ctor_builder->GetILGenerator(); + // call base .ctor + code->Emit( Emit::OpCodes::Ldarg_0 ); // push this + sal_Int32 base_members_length = all_members_length - members_length; + array< ::System::Type^>^ param_types = + gcnew array< ::System::Type^> ( base_members_length ); + for ( member_pos = 0; member_pos < base_members_length; ++member_pos ) + { + emit_ldarg( code, member_pos +1 ); + param_types[ member_pos ] = all_param_types[ member_pos ]; + } + code->Emit( + Emit::OpCodes::Call, + nullptr == base_type_entry + ? entry->m_base_type->GetConstructor( param_types ) + : base_type_entry->m_ctor ); + // initialize members + for ( member_pos = 0; member_pos < members_length; ++member_pos ) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); // push this + emit_ldarg( code, member_pos + base_members_length +1 ); + code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] ); + } + code->Emit( Emit::OpCodes::Ret ); + entry->m_ctor = ctor_builder; + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting {0} type {1}", + TypeClass_STRUCT == entry->m_xType->getTypeClass() + ? "struct" + : "exception", + cts_name); + } + // new entry + m_generated_structs->Add(cts_name, entry ); + ::System::Type ^ ret_type = entry->m_type_builder->CreateType(); + + // remove from incomplete types map + m_incomplete_structs->Remove( cts_name ); + entry->m_xType->release(); + + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting struct type {0}", cts_name); + } + return ret_type; +} + +//Examples of generated code +// public static XWeak constructor1(XComponentContext ctx) +// { +// XMultiComponentFactory factory = ctx.getServiceManager(); +// if (factory == null) +// throw new com.sun.star.uno.DeploymentException("bla", null); +// return (XWeak) factory.createInstanceWithContext("service_specifier", ctx); +// } +// public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c) +// { +// XMultiComponentFactory factory = ctx.getServiceManager(); +// if (factory == null) +// throw new com.sun.star.uno.DeploymentException("bla", null); +// Any[] arAny = new Any[3]; +// arAny[0] = new Any(typeof(int), a); +// arAny[1] = new Any(typeof(int), b); +// arAny[2] = new Any(c.Type, c.Value); +// return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx); +// } +// Notice that an any parameter is NOT wrapped by another any. Instead the new any is created with the type and value +// of the parameter. + +// public static XWeak constructor3(XComponentContext ctx, params Any[] c) +// { +// XMultiComponentFactory factory = ctx.getServiceManager(); +// if (factory == null) +// throw new com.sun.star.uno.DeploymentException("bla", null); +// return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx); +// } +::System::Type ^ TypeEmitter::complete_service_type(service_entry ^ entry) +{ + Emit::TypeBuilder ^ type_builder = entry->m_type_builder; + reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType; + + //Create the private default constructor + Emit::ConstructorBuilder^ ctor_builder = + type_builder->DefineConstructor( + (MethodAttributes) (MethodAttributes::Private | + MethodAttributes::HideBySig | + MethodAttributes::SpecialName | + MethodAttributes::RTSpecialName), + CallingConventions::Standard, nullptr); + + Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator(); + ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this + ilGen->Emit( + Emit::OpCodes::Call, + type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0))); + ilGen->Emit( Emit::OpCodes::Ret ); + + + //Create the service constructors. + //obtain the interface which makes up this service, it is the return + //type of the constructor functions + Reference xIfaceType( + xServiceType->getInterface(), UNO_QUERY); + if (xIfaceType.is () == sal_False) + xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface()); + System::Type ^ retType = get_type(xIfaceType); + + //Create the ConstructorInfo for a DeploymentException + ::System::Type ^ typeDeploymentExc = + get_type("unoidl.com.sun.star.uno.DeploymentException", true); + + array< ::System::Type^>^ arTypeCtor = {::System::String::typeid, + ::System::Object::typeid}; + ::System::Reflection::ConstructorInfo ^ ctorDeploymentException = + typeDeploymentExc->GetConstructor(arTypeCtor); + + Sequence > seqCtors = + xServiceType->getConstructors(); + + ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true); + + for (int i = seqCtors.getLength() - 1; i >= 0; i--) + { + bool bParameterArray = false; + ::System::Type ^ typeAny = ::uno::Any::typeid; + const Reference & ctorDes = + seqCtors[i]; + //obtain the parameter types + Sequence > seqParams = + ctorDes->getParameters(); + Reference const * arXParams = seqParams.getConstArray(); + sal_Int32 cParams = seqParams.getLength(); + array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1); + arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true); + for (int iparam = 0; iparam != cParams; iparam++) + { + if (arXParams[iparam]->isRestParameter()) + arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid; + else + arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType()); + } + //The array arTypeParameters can contain: + //System.Type and uno.PolymorphicType. + //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem. + //The exception will read something like no on information for parameter # d + //Maybe we need no override another Type method in PolymorphicType ... + //Until we have figured this out, we will create another array of System.Type which + //we pass on to DefineMethod. + array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1); +// arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true); + for (int i = 0; i < cParams + 1; i++) + { + ::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]); + if (pT) + arParamTypes[i] = pT->OriginalType; + else + arParamTypes[i] = arTypeParameters[i]; + } + //define method + System::String ^ ctorName; + if (ctorDes->isDefaultConstructor()) + ctorName = gcnew ::System::String("create"); + else + ctorName = ustring_to_String(ctorDes->getName()); + Emit::MethodBuilder^ method_builder = type_builder->DefineMethod( + ctorName, + static_cast(MethodAttributes::Public | MethodAttributes::HideBySig | + MethodAttributes::Static), + retType, +// arTypeParameters); + arParamTypes); + + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder^ attrBuilder = get_service_exception_attribute(ctorDes); + if (attrBuilder != nullptr) + method_builder->SetCustomAttribute(attrBuilder); + + + //define parameter attributes (paramarray), names etc. + //The first parameter is the XComponentContext, which cannot be obtained + //from reflection. + //The context is not part of the idl description + method_builder->DefineParameter( + 1, ParameterAttributes::In, "the_context"); + + array^ arParameterBuilder = + gcnew array (cParams); + for (int iparam = 0; iparam != cParams; iparam++) + { + Reference const & aParam = arXParams[iparam]; + ::System::String ^ sParamName = ustring_to_String(aParam->getName()); + + arParameterBuilder[iparam] = method_builder->DefineParameter( + iparam + 2, ParameterAttributes::In, sParamName); + + if (aParam->isRestParameter()) + { + bParameterArray = true; + //set the ParameterArrayAttribute + ::System::Reflection::ConstructorInfo^ ctor_info = + System::ParamArrayAttribute::typeid->GetConstructor( + gcnew array< ::System::Type^>(0)); + Emit::CustomAttributeBuilder ^ attr_builder = + gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew array< ::System::Object^>(0)); + arParameterBuilder[iparam]->SetCustomAttribute(attr_builder); + break; + } + } + + Emit::ILGenerator ^ ilGen = method_builder->GetILGenerator(); + + //Define locals --------------------------------- + //XMultiComponentFactory + Emit::LocalBuilder^ local_factory = + ilGen->DeclareLocal( + get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true)); + + //The return type + Emit::LocalBuilder^ local_return_val = + ilGen->DeclareLocal(retType); + + //Obtain the XMultiComponentFactory and throw an exception if we do not get one + ilGen->Emit(Emit::OpCodes::Ldarg_0); + + ::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type( + "unoidl.com.sun.star.uno.XComponentContext", true) + ->GetMethod("getServiceManager"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager); + ilGen->Emit(Emit::OpCodes::Stloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + Emit::Label label1 = ilGen->DefineLabel(); + ilGen->Emit(Emit::OpCodes::Brtrue, label1); + //The string for the exception + ::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256); + strbuilder->Append("The service "); + strbuilder->Append(to_cts_name(xServiceType->getName())); + strbuilder->Append(" could not be created. The context failed to supply the service manager."); + + ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); + ilGen->Emit(Emit::OpCodes::Throw); + ilGen->MarkLabel(label1); + + //We create a try/ catch around the createInstanceWithContext, etc. functions + //There are 3 cases + //1. function do not specify exceptions. Then RuntimeExceptions are re-thrown and other + // exceptions produce a DeploymentException. + //2. function specify Exception. Then all exceptions fly through + //3. function specifies exceptions but no Exception. Then these are rethrown + // and other exceptions, except RuntimeException, produce a deployment exception. + //In case there are no parameters we call + //XMultiComponentFactory.createInstanceWithContext + + ::System::Collections::ArrayList ^ arExceptionTypes = + get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions()); + if (arExceptionTypes->Contains( + type_uno_exception) == false) + { + ilGen->BeginExceptionBlock(); + } + if (cParams == 0) + { + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + + ::System::Reflection::MethodInfo ^ methodCreate = + local_factory->LocalType->GetMethod("createInstanceWithContext"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); + } + else if(bParameterArray) + { + //Service constructor with parameter array + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); + ilGen->Emit(Emit::OpCodes::Ldarg_1); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ::System::Reflection::MethodInfo ^ methodCreate = + local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); + } + else + { + // Any param1, Any param2, etc. + // For each parameter,except the component context, and parameter array + // and Any is created. + array^ arLocalAny = gcnew array (cParams); + + for (int iParam = 0; iParam < cParams; iParam ++) + { + arLocalAny[iParam] = ilGen->DeclareLocal(typeAny); + } + + //Any[]. This array is filled with the created Anys which contain the parameters + //and the values contained in the parameter array + Emit::LocalBuilder ^ local_anyParams = + ilGen->DeclareLocal(array< ::uno::Any>::typeid); + + //Create the Any for every argument, except for the parameter array + //arLocalAny contains the LocalBuilder for all these parameters. + //we call the ctor Any(Type, Object) + //If the parameter is an Any then the Any is created with Any(param.Type, param.Value); + array< ::System::Type^>^ arTypesCtorAny = {::System::Type::typeid, + ::System::Object::typeid}; + ::System::Reflection::ConstructorInfo ^ ctorAny = + typeAny->GetConstructor( arTypesCtorAny); + ::System::Reflection::MethodInfo ^ methodAnyGetType = + typeAny->GetProperty("Type")->GetGetMethod(); + ::System::Reflection::MethodInfo ^ methodAnyGetValue = + typeAny->GetProperty("Value")->GetGetMethod(); + for (int i = 0; i < arLocalAny->Length; i ++) + { + //check if the parameter is a polymorphic struct + ::uno::PolymorphicType ^polyType = dynamic_cast< ::uno::PolymorphicType^ >(arTypeParameters[i+1]); + //arTypeParameters[i+1] = polyType->OriginalType; + if (polyType) + { + //It is a polymorphic struct + //Load the uninitialized local Any on which we will call the ctor + ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); + // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName) + // Prepare the first parameter + ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->OriginalType); + array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid}; + ilGen->Emit(Emit::OpCodes::Call, + ::System::Type::typeid->GetMethod( + "GetTypeFromHandle", arTypeParams)); + // Prepare the second parameter + ilGen->Emit(Emit::OpCodes::Ldstr, polyType->PolymorphicName); + // Make the actual call + array< ::System::Type^>^ arTypeParam_GetType = { + ::System::Type::typeid, ::System::String::typeid }; + ilGen->Emit(Emit::OpCodes::Call, + ::uno::PolymorphicType::typeid->GetMethod(gcnew System::String("GetType"), + arTypeParam_GetType)); + + //Stack is: localAny, PolymorphicType + //Call Any::Any(Type, Object) + //Prepare the second parameter for the any ctor + ilGen->Emit(Emit::OpCodes::Ldarg, i + 1); + // if the parameter is a value type then we need to box it, because + // the Any ctor takes an Object + if (arTypeParameters[i+1]->IsValueType) + ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]); + ilGen->Emit(Emit::OpCodes::Call, ctorAny); + } + else if (arTypeParameters[i+1] == typeAny) + { + //Create the call new Any(param.Type,param,Value) + //Stack must be Any,Type,Value + //First load the Any which is to be constructed + ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); + //Load the Type, which is obtained by calling param.Type + ilGen->Emit(Emit::OpCodes::Ldarga, i + 1); + ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType); + //Load the Value, which is obtained by calling param.Value + ilGen->Emit(Emit::OpCodes::Ldarga, i + 1); + ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue); + //Call the Any ctor. + ilGen->Emit(Emit::OpCodes::Call, ctorAny); + } + else + { + ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); + ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]); + + array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid}; + ilGen->Emit(Emit::OpCodes::Call, + ::System::Type::typeid->GetMethod( + "GetTypeFromHandle", arTypeParams)); + ilGen->Emit(Emit::OpCodes::Ldarg, i + 1); + // if the parameter is a value type then we need to box it, because + // the Any ctor takes an Object + if (arTypeParameters[i+1]->IsValueType) + ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]); + ilGen->Emit(Emit::OpCodes::Call, ctorAny); + } + } + + //Create the Any[] that is passed to the + //createInstanceWithContext[AndArguments] function + ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length); + ilGen->Emit(Emit::OpCodes::Newarr, typeAny); + ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams); + + //Assign all anys created from the parameters + //array to the Any[] + for (int i = 0; i < arLocalAny->Length; i++) + { + ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams); + ilGen->Emit(Emit::OpCodes::Ldc_I4, i); + ilGen->Emit(Emit::OpCodes::Ldelema, typeAny); + ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]); + ilGen->Emit(Emit::OpCodes::Stobj, typeAny); + } + // call createInstanceWithArgumentsAndContext + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); + ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ::System::Reflection::MethodInfo ^ methodCreate = + local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); + } + //cast the object returned by the functions createInstanceWithContext or + //createInstanceWithArgumentsAndContext to the interface type + ilGen->Emit(Emit::OpCodes::Castclass, retType); + ilGen->Emit(Emit::OpCodes::Stloc, local_return_val); + + //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext + if (arExceptionTypes->Contains(type_uno_exception) == false) + { + // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;} + ilGen->BeginCatchBlock(get_type("unoidl.com.sun.star.uno.RuntimeException", true)); + ilGen->Emit(Emit::OpCodes::Pop); + ilGen->Emit(Emit::OpCodes::Rethrow); + + //catch and rethrow all other defined Exceptions + for (int i = 0; i < arExceptionTypes->Count; i++) + { + ::System::Type ^ excType = safe_cast< ::System::Type^ >( + arExceptionTypes[i]); + if (excType->IsInstanceOfType( + get_type("unoidl.com.sun.star.uno.RuntimeException", true))) + {// we have a catch for RuntimeException already defined + continue; + } + + //catch Exception and rethrow + ilGen->BeginCatchBlock(excType); + ilGen->Emit(Emit::OpCodes::Pop); + ilGen->Emit(Emit::OpCodes::Rethrow); + } + //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...} + ilGen->BeginCatchBlock(type_uno_exception); + + //Define the local variable that keeps the exception + Emit::LocalBuilder ^ local_exception = ilGen->DeclareLocal( + type_uno_exception); + + //Store the exception + ilGen->Emit(Emit::OpCodes::Stloc, local_exception); + + //prepare the construction of the exception + strbuilder = gcnew ::System::Text::StringBuilder(256); + strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service "); + strbuilder->Append(to_cts_name(xServiceType->getName())); + strbuilder->Append(": "); + + ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); + + //add to the string the Exception.Message + ilGen->Emit(Emit::OpCodes::Ldloc, local_exception); + ilGen->Emit(Emit::OpCodes::Callvirt, + type_uno_exception->GetProperty("Message")->GetGetMethod()); + array< ::System::Type^>^ arConcatParams = {System::String::typeid, + System::String::typeid}; + ilGen->Emit(Emit::OpCodes::Call, + System::String::typeid->GetMethod("Concat", arConcatParams)); + //load context argument + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); + ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc); + + ilGen->EndExceptionBlock(); + } + + + //Check if the service instance was created and threw an exception if not + Emit::Label label_service_created = ilGen->DefineLabel(); + ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val); + ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created); + + strbuilder = gcnew ::System::Text::StringBuilder(256); + strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service "); + strbuilder->Append(to_cts_name(xServiceType->getName())); + strbuilder->Append("."); + ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); + ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc); + + ilGen->MarkLabel(label_service_created); + ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val); + ilGen->Emit(Emit::OpCodes::Ret); + + } + // remove from incomplete types map + ::System::String ^ cts_name = type_builder->FullName; + m_incomplete_services->Remove( cts_name ); + xServiceType->release(); + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting service type {0}", cts_name ); + } + return type_builder->CreateType(); +} + + +Emit::CustomAttributeBuilder^ TypeEmitter::get_service_exception_attribute( + const Reference & ctorDes ) +{ + return get_exception_attribute(ctorDes->getExceptions()); +} + +Emit::CustomAttributeBuilder^ TypeEmitter::get_iface_method_exception_attribute( + const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod ) +{ + + const Sequence > seqTD = xMethod->getExceptions(); + int len = seqTD.getLength(); + Sequence > seqCTD(len); + Reference * arCTD = seqCTD.getArray(); + for (int i = 0; i < len; i++) + arCTD[i] = Reference(seqTD[i], UNO_QUERY_THROW); + return get_exception_attribute(seqCTD); +} + +Emit::CustomAttributeBuilder^ TypeEmitter::get_exception_attribute( + + const Sequence >& seq_exceptionsTd ) +{ + Emit::CustomAttributeBuilder ^ attr_builder = nullptr; + + Reference< reflection::XCompoundTypeDescription > const * exceptions = + seq_exceptionsTd.getConstArray(); + + array< ::System::Type^>^ arTypesCtor = {::System::Type::GetType("System.Type[]")}; + ConstructorInfo ^ ctor_ExceptionAttribute = + ::uno::ExceptionAttribute::typeid->GetConstructor(arTypesCtor); + + sal_Int32 exc_length = seq_exceptionsTd.getLength(); + if (exc_length != 0) // opt + { + array< ::System::Type^>^ exception_types = + gcnew array< ::System::Type^> ( exc_length ); + for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos ) + { + Reference< reflection::XCompoundTypeDescription > const & xExc = + exceptions[ exc_pos ]; + exception_types[ exc_pos ] = get_type( xExc ); + } + array< ::System::Object^>^ args = {exception_types}; + attr_builder = gcnew Emit::CustomAttributeBuilder( + ctor_ExceptionAttribute, args ); + } + return attr_builder; +} + + +::System::Type ^ TypeEmitter::complete_singleton_type(singleton_entry ^ entry) +{ + Emit::TypeBuilder ^ type_builder = entry->m_type_builder; + reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType; + ::System::String^ sSingletonName = to_cts_name(xSingletonType->getName()); + + //Create the private default constructor + Emit::ConstructorBuilder^ ctor_builder = + type_builder->DefineConstructor( + static_cast(MethodAttributes::Private | + MethodAttributes::HideBySig | + MethodAttributes::SpecialName | + MethodAttributes::RTSpecialName), + CallingConventions::Standard, nullptr); + + Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator(); + ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this + ilGen->Emit( + Emit::OpCodes::Call, + type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0))); + ilGen->Emit( Emit::OpCodes::Ret ); + + + //obtain the interface which makes up this service, it is the return + //type of the constructor functions + Reference xIfaceType( + xSingletonType->getInterface(), UNO_QUERY); + if (xIfaceType.is () == sal_False) + xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface()); + System::Type ^ retType = get_type(xIfaceType); + + //define method + array< ::System::Type^>^ arTypeParameters = {get_type("unoidl.com.sun.star.uno.XComponentContext", true)}; + Emit::MethodBuilder^ method_builder = type_builder->DefineMethod( + gcnew System::String("get"), + static_cast(MethodAttributes::Public | MethodAttributes::HideBySig | + MethodAttributes::Static), + retType, + arTypeParameters); + + +// method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes)); + + //The first parameter is the XComponentContext, which cannot be obtained + //from reflection. + //The context is not part of the idl description + method_builder->DefineParameter(1, ParameterAttributes::In, "the_context"); + + + ilGen = method_builder->GetILGenerator(); + //Define locals --------------------------------- + // Any, returned by XComponentContext.getValueByName + Emit::LocalBuilder^ local_any = + ilGen->DeclareLocal(::uno::Any::typeid); + + //Call XContext::getValueByName + ilGen->Emit(Emit::OpCodes::Ldarg_0); + // build the singleton name : /singleton/unoidl.com.sun.star.XXX + ::System::Text::StringBuilder^ sBuilder = + gcnew ::System::Text::StringBuilder("/singletons/"); + sBuilder->Append(sSingletonName); + ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString()); + + ::System::Reflection::MethodInfo ^ methodGetValueByName = + get_type("unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod("getValueByName"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName); + ilGen->Emit(Emit::OpCodes::Stloc_0); + + //Contains the returned Any a value? + ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any); + ::System::Reflection::MethodInfo ^ methodHasValue = + ::uno::Any::typeid->GetMethod("hasValue"); + ilGen->Emit(Emit::OpCodes::Call, methodHasValue); + + //If not, then throw a DeploymentException + Emit::Label label_singleton_exists = ilGen->DefineLabel(); + ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists); + sBuilder = gcnew ::System::Text::StringBuilder( + "Component context fails to supply singleton "); + sBuilder->Append(sSingletonName); + sBuilder->Append(" of type "); + sBuilder->Append(retType->FullName); + sBuilder->Append("."); + ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString()); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + array< ::System::Type^>^ arTypesCtorDeploymentException = { + ::System::String::typeid, ::System::Object::typeid}; + ilGen->Emit(Emit::OpCodes::Newobj, + get_type("unoidl.com.sun.star.uno.DeploymentException",true) + ->GetConstructor(arTypesCtorDeploymentException)); + ilGen->Emit(Emit::OpCodes::Throw); + ilGen->MarkLabel(label_singleton_exists); + + //Cast the singleton contained in the Any to the expected interface and return it. + ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any); + ilGen->Emit(Emit::OpCodes::Call, ::uno::Any::typeid->GetProperty("Value")->GetGetMethod()); + ilGen->Emit(Emit::OpCodes::Castclass, retType); + ilGen->Emit(Emit::OpCodes::Ret); + + // remove from incomplete types map + ::System::String ^ cts_name = type_builder->FullName; + m_incomplete_singletons->Remove( cts_name ); + xSingletonType->release(); + if (g_bVerbose) + { + ::System::Console::WriteLine( + "> emitting singleton type {0}", cts_name ); + } + return type_builder->CreateType(); +} + + +::System::Type ^ TypeEmitter::get_type( + Reference< reflection::XTypeDescription > const & xType ) +{ + switch (xType->getTypeClass()) + { + case TypeClass_VOID: + return ::System::Void::typeid; + case TypeClass_CHAR: + return ::System::Char::typeid; + case TypeClass_BOOLEAN: + return ::System::Boolean::typeid; + case TypeClass_BYTE: + return ::System::Byte::typeid; + case TypeClass_SHORT: + return ::System::Int16::typeid; + case TypeClass_UNSIGNED_SHORT: + return ::System::UInt16::typeid; + case TypeClass_LONG: + return ::System::Int32::typeid; + case TypeClass_UNSIGNED_LONG: + return ::System::UInt32::typeid; + case TypeClass_HYPER: + return ::System::Int64::typeid; + case TypeClass_UNSIGNED_HYPER: + return ::System::UInt64::typeid; + case TypeClass_FLOAT: + return ::System::Single::typeid; + case TypeClass_DOUBLE: + return ::System::Double::typeid; + case TypeClass_STRING: + return ::System::String::typeid; + case TypeClass_TYPE: + return ::System::Type::typeid; + case TypeClass_ANY: + return ::uno::Any::typeid; + case TypeClass_ENUM: + return get_type( Reference< reflection::XEnumTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_TYPEDEF: + // unwind typedefs + return get_type( + Reference< reflection::XIndirectTypeDescription >( + xType, UNO_QUERY_THROW )->getReferencedType() ); + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + return get_type( + Reference< reflection::XCompoundTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_SEQUENCE: + { + ::System::Type ^ element_type = get_type( + Reference< reflection::XIndirectTypeDescription >( + xType, UNO_QUERY_THROW )->getReferencedType() ); + ::System::Type ^ retType = get_type( + ::System::String::Concat( + element_type->FullName, "[]" ), true ); + + ::uno::PolymorphicType ^ pt = dynamic_cast< ::uno::PolymorphicType ^ >(element_type); + if (pt) + { + ::System::String ^ sName = ::System::String::Concat(pt->PolymorphicName, "[]"); + retType = ::uno::PolymorphicType::GetType(retType, sName); + } + return retType; + } + case TypeClass_INTERFACE: + return get_type( + Reference< reflection::XInterfaceTypeDescription2 >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_CONSTANT: + return get_type( + Reference< reflection::XConstantTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_CONSTANTS: + return get_type( + Reference< reflection::XConstantsTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_SERVICE: + return get_type( + Reference< reflection::XServiceTypeDescription2 >( + xType, UNO_QUERY_THROW) ); + case TypeClass_SINGLETON: + return get_type( + Reference< reflection::XSingletonTypeDescription2 >( + xType, UNO_QUERY_THROW) ); + case TypeClass_MODULE: + // ignore these + return nullptr; + default: + throw RuntimeException( + "unexpected type " + xType->getName() ); + } +} + + +::System::Type ^ TypeEmitter::get_complete_struct( ::System::String ^ sName) +{ + struct_entry ^ pStruct = safe_cast< struct_entry ^>( + m_incomplete_structs[sName]); + if (pStruct) + { + complete_struct_type(pStruct); + } + //get_type will asked the module builder for the type or otherwise all known assemblies. + return get_type(sName, true); +} +void TypeEmitter::finish() +{ + while (true) + { + ::System::Collections::IDictionaryEnumerator ^ enumerator = + m_incomplete_ifaces->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_iface_type( + safe_cast< iface_entry ^ >( enumerator->Value ) ); + } + + while (true) + { + ::System::Collections::IDictionaryEnumerator ^ enumerator = + m_incomplete_structs->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_struct_type( + safe_cast< struct_entry ^ >( enumerator->Value ) ); + } + + + while (true) + { + ::System::Collections::IDictionaryEnumerator ^ enumerator = + m_incomplete_services->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_service_type( + safe_cast< service_entry ^ >( enumerator->Value ) ); + } + + while (true) + { + ::System::Collections::IDictionaryEnumerator ^ enumerator = + m_incomplete_singletons->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_singleton_type( + safe_cast< singleton_entry ^ >( enumerator->Value ) ); + } +} + +TypeEmitter::TypeEmitter( + ::System::Reflection::Emit::ModuleBuilder ^ module_builder, + array< ::System::Reflection::Assembly^>^ extra_assemblies ) + : m_module_builder( module_builder ), + m_extra_assemblies( extra_assemblies ), + m_method_info_Type_GetTypeFromHandle( nullptr ), + m_type_Exception( nullptr ), + m_type_RuntimeException( nullptr ), + m_incomplete_ifaces( gcnew ::System::Collections::Hashtable() ), + m_incomplete_structs( gcnew ::System::Collections::Hashtable() ), + m_incomplete_services(gcnew ::System::Collections::Hashtable() ), + m_incomplete_singletons(gcnew ::System::Collections::Hashtable() ), + m_generated_structs( gcnew ::System::Collections::Hashtable() ) +{ + array< ::System::Type^>^ param_types = gcnew array< ::System::Type^> ( 1 ); + param_types[ 0 ] = ::System::RuntimeTypeHandle::typeid; + m_method_info_Type_GetTypeFromHandle = + ::System::Type::typeid + ->GetMethod( "GetTypeFromHandle", param_types ); +} + +::System::Collections::ArrayList ^ TypeEmitter::get_service_ctor_method_exceptions_reduced( + const Sequence > & seqExceptionsTd) +{ + if (seqExceptionsTd.getLength() == 0) + return gcnew ::System::Collections::ArrayList(); + + ::System::Collections::ArrayList ^ arTypes = gcnew ::System::Collections::ArrayList(); + for (int i = 0; i < seqExceptionsTd.getLength(); i++) + arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true)); + + int start = 0; + while (true) + { + bool bRemove = false; + for (int i = start; i < arTypes->Count; i++) + { + ::System::Type ^ t = safe_cast< ::System::Type^ >(arTypes[i]); + for (int j = 0; j < arTypes->Count; j++) + { + if (t->IsSubclassOf(safe_cast< ::System::Type^ >(arTypes[j]))) + { + arTypes->RemoveAt(i); + bRemove = true; + break; + } + } + if (bRemove) + break; + start++; + } + + if (bRemove == false) + break; + } + return arTypes; +} + + +css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > +resolveInterfaceTypedef( + const css::uno::Reference& type) +{ + Reference + xIfaceTd(type, UNO_QUERY); + + if (xIfaceTd.is()) + return xIfaceTd; + + Reference xIndTd( + type, UNO_QUERY_THROW); + + return resolveInterfaceTypedef(xIndTd->getReferencedType()); +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cli_ure/source/climaker/climaker_share.h b/cli_ure/source/climaker/climaker_share.h new file mode 100644 index 0000000000..29c3c87642 --- /dev/null +++ b/cli_ure/source/climaker/climaker_share.h @@ -0,0 +1,258 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#using + +#include + +#include "osl/diagnose.h" +#include "com/sun/star/reflection/XConstantTypeDescription.hpp" +#include "com/sun/star/reflection/XConstantsTypeDescription.hpp" +#include "com/sun/star/reflection/XEnumTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XCompoundTypeDescription.hpp" +#include "com/sun/star/reflection/XServiceTypeDescription2.hpp" +#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" + + +namespace climaker +{ + + +extern bool g_bVerbose; + +ref struct Constants +{ + static ::System::String ^ sUnoVoid = "void"; + static ::System::String ^ sUnoType = "type"; + static ::System::String ^ sUnoAny = "any"; + static ::System::String ^ sUnoBool = "boolean"; + static ::System::String ^ sUnoByte = "byte"; + static ::System::String ^ sUnoChar = "char"; + static ::System::String ^ sUnoShort = "short"; + static ::System::String ^ sUnoUShort = "unsigned short"; + static ::System::String ^ sUnoLong = "long"; + static ::System::String ^ sUnoULong = "unsigned long"; + static ::System::String ^ sUnoHyper = "hyper"; + static ::System::String ^ sUnoUHyper = "unsigned hyper"; + static ::System::String ^ sUnoString = "string"; + static ::System::String ^ sUnoFloat = "float"; + static ::System::String ^ sUnoDouble = "double"; + static ::System::String ^ sUnoXInterface = "com.sun.star.uno.XInterface"; + static ::System::String ^ sBrackets = "[]"; + + static System::String^ sObject = "System.Object"; + static System::String^ sType = "System.Type"; + static System::String^ sUnoidl = "unoidl."; + static System::String^ sVoid = "System.Void"; + static System::String^ sAny = "uno.Any"; + static System::String^ sBoolean = "System.Boolean"; + static System::String^ sChar = "System.Char"; + static System::String^ sByte = "System.Byte"; + static System::String^ sInt16 = "System.Int16"; + static System::String^ sUInt16 = "System.UInt16"; + static System::String^ sInt32 = "System.Int32"; + static System::String^ sUInt32 = "System.UInt32"; + static System::String^ sInt64 = "System.Int64"; + static System::String^ sUInt64 = "System.UInt64"; + static System::String^ sString = "System.String"; + static System::String^ sSingle = "System.Single"; + static System::String^ sDouble = "System.Double"; + static System::String^ sComma = gcnew System::String(","); + +}; + + +inline ::System::String ^ ustring_to_String( OUString const & ustr ) +{ + return gcnew ::System::String( + reinterpret_cast(ustr.getStr()), 0, ustr.getLength()); +} + + +inline OUString String_to_ustring( ::System::String ^ str ) +{ + OSL_ASSERT( sizeof (wchar_t) == sizeof (sal_Unicode) ); + pin_ptr chars = PtrToStringChars( str ); + return OUString(reinterpret_cast(chars), str->Length); +} + +/* If the argument type is a typedef for an interface then the interface + type description is returned, otherwise an exception is thrown. +*/ +css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > +resolveInterfaceTypedef(const css::uno::Reference& type); + +static ::System::Reflection::MethodAttributes c_ctor_method_attr = +(::System::Reflection::MethodAttributes) + (::System::Reflection::MethodAttributes::Public | + ::System::Reflection::MethodAttributes::HideBySig | + ::System::Reflection::MethodAttributes::SpecialName | + ::System::Reflection::MethodAttributes::RTSpecialName + /* | xxx todo: ??? compiler does not know Instance ??? + ::System::Reflection::MethodAttributes::Instance*/); + + +ref class TypeEmitter +{ + ::System::Reflection::Emit::ModuleBuilder ^ m_module_builder; + array< ::System::Reflection::Assembly^>^ m_extra_assemblies; + + ::System::Reflection::MethodInfo ^ m_method_info_Type_GetTypeFromHandle; + + ::System::Type ^ m_type_Exception; + ::System::Type ^ get_type_Exception(); + ::System::Type ^ m_type_RuntimeException; + ::System::Type ^ get_type_RuntimeException(); + + ::System::Reflection::Emit::CustomAttributeBuilder^ get_service_exception_attribute( + const css::uno::Reference & ctorDesc); + ::System::Reflection::Emit::CustomAttributeBuilder^ get_iface_method_exception_attribute( + const css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription >& xMethod ); + ::System::Reflection::Emit::CustomAttributeBuilder^ get_exception_attribute( + const css::uno::Sequence >& seq_exceptionsTd ); +/* Creates ::System::Type object for UNO exceptions. The UNO exceptions are + obtained by + css::reflection::XServiceConstructorDescription::getExceptions + In a first step the respective CLI types are created. Then it is examined + if a Type represents a super class of another class. If so the Type of the + derived class is discarded. For example there are a uno RuntimeException and + a DeploymentException which inherits RuntimeException. Then only the cli Type + of the RuntimeException is returned. + The purpose of this function is to provide exceptions for which catch blocks + are generated in the service constructor code. + + It is always an instance of an ArrayList returned, even if the sequence argument + does not contain elements. + */ + ::System::Collections::ArrayList ^ get_service_ctor_method_exceptions_reduced( + const css::uno::Sequence< + css::uno::Reference > & seqExceptionsTd); + + + ref class iface_entry + { + public: + css::reflection::XInterfaceTypeDescription2 * m_xType; + ::System::Reflection::Emit::TypeBuilder ^ m_type_builder; + }; + ::System::Collections::Hashtable ^ m_incomplete_ifaces; + ::System::Type ^ complete_iface_type( iface_entry ^ entry ); + + ref class struct_entry + { + public: + css::reflection::XCompoundTypeDescription * m_xType; + ::System::Reflection::Emit::TypeBuilder ^ m_type_builder; + ::System::Type ^ m_base_type; + + array< ::System::String^>^ m_member_names; + array< ::System::Type^>^ m_param_types; + ::System::Reflection::ConstructorInfo ^ m_default_ctor; + ::System::Reflection::ConstructorInfo ^ m_ctor; + }; + ::System::Collections::Hashtable ^ m_incomplete_structs; + ::System::Type ^ complete_struct_type( struct_entry ^ entry ); + + /* returns the type for the name. If it is a struct then it may + complete the struct if not already done. This also refers to its + base types. + + @param sName + the full name of the type. + @return the type object for sName. Not necessarily a struct. + */ + ::System::Type ^ get_complete_struct( ::System::String ^ sName); + + ref class service_entry + { + public: + ::System::Reflection::Emit::TypeBuilder ^ m_type_builder; + css::reflection::XServiceTypeDescription2 * m_xType; + }; + ::System::Collections::Hashtable ^ m_incomplete_services; + ::System::Type ^ complete_service_type(service_entry ^ entry); + + ref class singleton_entry + { + public: + ::System::Reflection::Emit::TypeBuilder ^ m_type_builder; + css::reflection::XSingletonTypeDescription2 * m_xType; + }; + + + ::System::Collections::Hashtable ^ m_incomplete_singletons; + ::System::Type ^ complete_singleton_type(singleton_entry ^ entry); + + + ::System::Collections::Hashtable ^ m_generated_structs; + + ::System::Type ^ get_type( + ::System::String ^ cli_name, bool throw_exc ); + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XConstantTypeDescription > const & xType ); + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XConstantsTypeDescription > const & xType ); + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XEnumTypeDescription > const & xType ); + /* returns the type for a struct or exception. In case of a polymorphic struct it may + return a ::uno::PolymorphicType (cli_basetypes.dll) only if the struct is already + complete. + */ + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XCompoundTypeDescription > const & xType ); + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XInterfaceTypeDescription2 > const & xType ); + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XSingletonTypeDescription2 > const & xType ); + + /* + May return NULL if the service description is an obsolete. See + description of + com.sun.star.reflection.XServiceTypeDescription2.isSingleInterfaceBased + */ + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XServiceTypeDescription2 > const & xType ); +public: + TypeEmitter( + ::System::Reflection::Emit::ModuleBuilder ^ module_builder, + array< ::System::Reflection::Assembly^>^ assemblies ); + // must be called to finish up uncompleted types + void finish(); + + ::System::Reflection::Assembly ^ type_resolve( + ::System::Object ^ sender, ::System::ResolveEventArgs ^ args ); + + ::System::Type ^ get_type( + css::uno::Reference< + css::reflection::XTypeDescription > const & xType ); +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cli_ure/source/cliuno.snk b/cli_ure/source/cliuno.snk new file mode 100644 index 0000000000..938f16939f Binary files /dev/null and b/cli_ure/source/cliuno.snk differ diff --git a/cli_ure/source/native/assembly.cxx b/cli_ure/source/native/assembly.cxx new file mode 100644 index 0000000000..75e33e8c7f --- /dev/null +++ b/cli_ure/source/native/assembly.cxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +[assembly:System::Reflection::AssemblyProduct("CLI-UNO Language Binding")]; +[assembly:System::Reflection::AssemblyDescription("CLI-UNO Helper Library")]; +[assembly:System::Reflection::AssemblyDelaySign(true)]; +[assembly:System::Reflection::AssemblyCompany("OpenOffice.org")]; +[assembly:System::Reflection::AssemblyVersion("@CLI_CPPUHELPER_NEW_VERSION@")]; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cli_ure/source/native/cli_cppuhelper_config b/cli_ure/source/native/cli_cppuhelper_config new file mode 100644 index 0000000000..627a3a564f --- /dev/null +++ b/cli_ure/source/native/cli_cppuhelper_config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/cli_ure/source/native/native_bootstrap.cxx b/cli_ure/source/native/native_bootstrap.cxx new file mode 100644 index 0000000000..f26a634c2a --- /dev/null +++ b/cli_ure/source/native/native_bootstrap.cxx @@ -0,0 +1,297 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "native_share.h" + +#include "rtl/bootstrap.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "cppuhelper/bootstrap.hxx" +#include +#include +#define WIN32_LEAN_AND_MEAN +#include +#include + +#define INSTALL_PATH L"Software\\LibreOffice\\UNO\\InstallPath" +#define UNO_PATH L"UNO_PATH" + +namespace { + +/* Gets the installation path from the Windows Registry for the specified + registry key. + + @param hroot open handle to predefined root registry key + @param subKeyName name of the subkey to open + + @return the installation path or nullptr, if no installation was found or + if an error occurred +*/ +WCHAR* getPathFromRegistryKey( HKEY hroot, LPCWSTR subKeyName ) +{ + // open the specified registry key + HKEY hkey; + if ( RegOpenKeyExW( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS ) + return nullptr; + + struct CloseKeyGuard { + HKEY m_hkey; + ~CloseKeyGuard() { RegCloseKey( m_hkey ); } + } aCloseKeyGuard{hkey}; + + // find the type and size of the default value + DWORD type; + DWORD size; + if ( RegQueryValueExW( hkey, nullptr, nullptr, &type, nullptr, &size ) != ERROR_SUCCESS ) + return nullptr; + + // get memory to hold the default value + std::unique_ptr data(new WCHAR[size]); + + // read the default value + if ( RegQueryValueExW( hkey, nullptr, nullptr, &type, reinterpret_cast(data.get()), &size ) != ERROR_SUCCESS ) + return nullptr; + + return data.release(); +} + +/* Returns the path to the program folder of the brand layer, + for example C:/Program Files/LibreOffice/program + This path is either obtained from the environment variable UNO_PATH + or the registry item "Software\\LibreOffice\\UNO\\InstallPath" + either in HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE + The return value must be freed with delete[] +*/ +WCHAR* getInstallPath() +{ + std::unique_ptr szInstallPath; + + DWORD cChars = GetEnvironmentVariableW(UNO_PATH, nullptr, 0); + if (cChars > 0) + { + szInstallPath.reset(new WCHAR[cChars]); + cChars = GetEnvironmentVariableW(UNO_PATH, szInstallPath.get(), cChars); + // If PATH is not set then it is no error + if (cChars == 0) + return nullptr; + } + + if (! szInstallPath) + { + szInstallPath.reset(getPathFromRegistryKey( HKEY_CURRENT_USER, INSTALL_PATH )); + if (! szInstallPath) + { + // read the key's default value from HKEY_LOCAL_MACHINE + szInstallPath.reset(getPathFromRegistryKey( HKEY_LOCAL_MACHINE, INSTALL_PATH )); + } + } + return szInstallPath.release(); +} + +/* We extend the path to contain the install folder, + so that components can use osl_loadModule with arguments, such as + "reg3.dll". That is, the arguments are only the library names. +*/ +void extendPath(LPCWSTR szPath) +{ + if (!szPath) + return; + + std::unique_ptr sEnvPath; + DWORD cChars = GetEnvironmentVariableW(L"PATH", nullptr, 0); + if (cChars > 0) + { + sEnvPath.reset(new WCHAR[cChars]); + cChars = GetEnvironmentVariableW(L"PATH", sEnvPath.get(), cChars); + // If PATH is not set then it is no error + if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) + return; + } + // Prepare the new PATH. Add the directory at the front. + // Note also adding ';' + std::unique_ptr sNewPath(new WCHAR[lstrlenW(sEnvPath.get()) + lstrlenW(szPath) + 2]); + lstrcpyW(sNewPath.get(), szPath); + if (lstrlenW(sEnvPath.get())) + { + lstrcatW(sNewPath.get(), L";"); + lstrcatW(sNewPath.get(), sEnvPath.get()); + } + SetEnvironmentVariableW(L"PATH", sNewPath.get()); +} + +HMODULE loadFromPath(LPCSTR sLibName) +{ + if (!sLibName) + return nullptr; + + // Convert the ansi file name to wchar_t* + int size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sLibName, -1, nullptr, 0); + if (size == 0) + return nullptr; + std::unique_ptr wsLibName(new WCHAR[size]); + if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sLibName, -1, wsLibName.get(), size)) + return nullptr; + + std::unique_ptr szPath(getInstallPath()); + if (!szPath) + return nullptr; + + extendPath(szPath.get()); + + std::unique_ptr szFullPath(new WCHAR[lstrlenW(wsLibName.get()) + lstrlenW(szPath.get()) + 2]); + lstrcpyW(szFullPath.get(), szPath.get()); + lstrcatW(szFullPath.get(), L"\\"); + lstrcatW(szFullPath.get(), wsLibName.get()); + HMODULE handle = LoadLibraryW(szFullPath.get()); + return handle; +} + +/* Hook for delayed loading of libraries which this library is linked with. + This is a failure hook. That is, it is only called when the loading of + a library failed. It will be called when loading of cppuhelper failed. + Because we extend the PATH to the install folder while this function is + executed (see extendPath), all other libraries are found. +*/ +extern "C" FARPROC WINAPI delayLoadHook( + unsigned int dliNotify, + PDelayLoadInfo pdli + ) +{ + if (dliNotify == dliFailLoadLib) + { + HANDLE h = loadFromPath(pdli->szDll); + return reinterpret_cast(h); + } + return nullptr; +} +} + +ExternC +const PfnDliHook __pfnDliFailureHook2 = delayLoadHook; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace uno +{ +namespace util +{ + +/** Bootstrapping native UNO. + + Bootstrapping requires the existence of many libraries which are contained + in an URE installation. To find and load these libraries the Windows + registry keys HKEY_CURRENT_USER\Software\LibreOffice\Layer\URE\1 + and HKEY_LOCAL_MACHINE\Software\LibreOffice\Layer\URE\1 are examined. + These contain a named value UREINSTALLLOCATION which holds a path to the URE + installation folder. +*/ +public ref class Bootstrap sealed +{ + inline Bootstrap() {} + +public: + + /** Bootstraps the initial component context from a native UNO installation. + + @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext() + */ + static ::unoidl::com::sun::star::uno::XComponentContext ^ + defaultBootstrap_InitialComponentContext(); + + /** Bootstraps the initial component context from a native UNO installation. + + @param ini_file + a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must + reside next to the cppuhelper library) + @param bootstrap_parameters + bootstrap parameters (maybe null) + + @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext() + */ + static ::unoidl::com::sun::star::uno::XComponentContext ^ + defaultBootstrap_InitialComponentContext( + ::System::String ^ ini_file, + ::System::Collections::IDictionaryEnumerator ^ + bootstrap_parameters ); + + /** Bootstraps the initial component context from a native UNO installation. + + @see cppuhelper/bootstrap.hxx:bootstrap() + */ + static ::unoidl::com::sun::star::uno::XComponentContext ^ + bootstrap(); +}; + + +::unoidl::com::sun::star::uno::XComponentContext ^ +Bootstrap::defaultBootstrap_InitialComponentContext( + ::System::String ^ ini_file, + ::System::Collections::IDictionaryEnumerator ^ bootstrap_parameters ) +{ + if (nullptr != bootstrap_parameters) + { + bootstrap_parameters->Reset(); + while (bootstrap_parameters->MoveNext()) + { + OUString key( + String_to_ustring( safe_cast< ::System::String ^ >( + bootstrap_parameters->Key ) ) ); + OUString value( + String_to_ustring( safe_cast< ::System::String ^ >( + bootstrap_parameters->Value ) ) ); + + ::rtl::Bootstrap::set( key, value ); + } + } + + // bootstrap native uno + Reference< XComponentContext > xContext; + if (nullptr == ini_file) + { + xContext = ::cppu::defaultBootstrap_InitialComponentContext(); + } + else + { + xContext = ::cppu::defaultBootstrap_InitialComponentContext( + String_to_ustring( safe_cast< ::System::String ^ >( ini_file ) ) ); + } + + return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >( + to_cli( xContext ) ); +} + + +::unoidl::com::sun::star::uno::XComponentContext ^ +Bootstrap::defaultBootstrap_InitialComponentContext() +{ + return defaultBootstrap_InitialComponentContext( nullptr, nullptr ); +} + +::unoidl::com::sun::star::uno::XComponentContext ^ Bootstrap::bootstrap() +{ + Reference xContext = ::cppu::bootstrap(); + return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >( + to_cli( xContext ) ); + +} + +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cli_ure/source/native/native_share.h b/cli_ure/source/native/native_share.h new file mode 100644 index 0000000000..f733d2558c --- /dev/null +++ b/cli_ure/source/native/native_share.h @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#using "cli_ure.dll" +#using "cli_uretypes.dll" + +#include "rtl/ustring.hxx" +#include +#include "uno/mapping.hxx" + +#include + + +namespace uno +{ +namespace util +{ + + +inline ::System::String ^ ustring_to_String( OUString const & ustr ) +{ + return gcnew ::System::String( + reinterpret_cast(ustr.getStr()), 0, ustr.getLength()); +} + +inline OUString String_to_ustring( ::System::String ^ str ) +{ + OSL_ASSERT( sizeof (wchar_t) == sizeof (sal_Unicode) ); + pin_ptr chars = PtrToStringChars( str ); + return OUString(reinterpret_cast(chars), str->Length); +} + +template< typename T > +inline ::System::Object ^ to_cli( + css::uno::Reference< T > const & x ) +{ + css::uno::Mapping mapping( + CPPU_CURRENT_LANGUAGE_BINDING_NAME, UNO_LB_CLI ); + OSL_ASSERT( mapping.is() ); + if (! mapping.is()) + { + throw css::uno::RuntimeException( + "cannot get mapping from C++ to CLI!", + css::uno::Reference< + css::uno::XInterface >() ); + } + + intptr_t intptr = + reinterpret_cast< intptr_t >( + mapping.mapInterface( x.get(), cppu::UnoType::get() ) ); + ::System::Runtime::InteropServices::GCHandle ^ handle = ::System::Runtime::InteropServices::GCHandle::FromIntPtr(::System::IntPtr(intptr)); + ::System::Object ^ ret = handle->Target; + handle->Free(); + return ret; +} + +template< typename T > +inline void to_uno( + css::uno::Reference< T > * pRet, ::System::Object ^ x ) +{ + css::uno::Mapping mapping( + UNO_LB_CLI, CPPU_CURRENT_LANGUAGE_BINDING_NAME ); + OSL_ASSERT( mapping.is() ); + if (! mapping.is()) + { + throw css::uno::RuntimeException( + "cannot get mapping from CLI to C++!", + css::uno::Reference< + css::uno::XInterface >() ); + } + + ::System::Runtime::InteropServices::GCHandle handle( + ::System::Runtime::InteropServices::GCHandle::Alloc( x ) ); + T * ret = 0; + mapping.mapInterface( + reinterpret_cast< void ** >( &ret ), + reinterpret_cast< void * >( + ::System::Runtime::InteropServices::GCHandle::op_Explicit( handle ) +#if defined _WIN64 + .ToInt64() +#elif defined _WIN32 + .ToInt32() +#else +#error ERROR: either _WIN64 or _WIN32 must be defined + ERROR: either _WIN64 or _WIN32 must be defined +#endif + ), + cppu::UnoType::get() ); + handle.Free(); + pRet->set( ret, SAL_NO_ACQUIRE /* takeover ownership */ ); +} + +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cli_ure/source/native/path.cxx b/cli_ure/source/native/path.cxx new file mode 100644 index 0000000000..6fae513149 --- /dev/null +++ b/cli_ure/source/native/path.cxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "sal/config.h" + +#if defined(_WIN32) + +#define WIN32_LEAN_AND_MEAN +#include + +#include "sal/types.h" + +namespace cli_ure { + +SAL_DLLPUBLIC_EXPORT WCHAR * filename(WCHAR * path) { + WCHAR * f = path; + for (WCHAR * p = path;;) { + switch (*p++) { + case L'\0': + return f; + case L'\\': + f = p; + break; + } + } +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cli_ure/source/scripts/increment_version.pl b/cli_ure/source/scripts/increment_version.pl new file mode 100644 index 0000000000..df0c677a89 --- /dev/null +++ b/cli_ure/source/scripts/increment_version.pl @@ -0,0 +1,273 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +use warnings; +use strict; +use diagnostics; + +sub trim; +sub readIncVersions($); +sub processLine($$); +sub checkName($); +sub incrementNewVersion($); +sub incrementOldVersion($); +sub incrementPolicyVersion($); +my $usage = +"The tool increments the minor version of assemblies and the major version of ". +"the respective policy files. This is only done if new uno types have been added since". +"the last product update. This information is obtained from the file which is passed as ". +"argument changedTypes. The names in the version file must have a particular form. ". +"They must end on one of following terms: NEW_VERSION, OLD_VERSION, POLICY_VERSION\n". +"If no new published types have been added then no output, argument newVersions, is written". +"Usage is: \n increment_version.pl oldVersions incVersions newVersions changedTypes\n\n". +"oldVersion: Contains name value pairs, which are used for forming the config files of ". +"the policy assemblies, for building the assemblies. \n\n". +"incVersions: File containing the names of which the versions are to be incremented. ". +"Every line may only contain one name. The names must exactly match those from the ". +"oldVersion file.\n\n". +"newVersions: Contains all entries from oldVersions, but the values of the names,". +"which occur in selection, have been incremented.\n\n". +"changedTypes: File that contains the information if new published types have been added ". +"since the last product update.\n\n" ; + +my $sNameForm = +"The names must end on one of these names: NEW_VERSION, OLD_VERSION, POLICY_VERSION\n". +"For example, valid names are: \n". +"CLI_URETYPES_NEW_VERSION\nCLI_URETYPES_OLD_VERSION\nCLI_URETYPES_POLICY_VERSION\n"; + +if (scalar @ARGV < 3) { + print $usage; + exit -1; +} + +-e "$ARGV[0]" or die "Error: wrong arguments. \n".$usage; +-e "$ARGV[1]" or die "Error: wrong arguments. \n".$usage; +#-e "$ARGV[3]" or die "Error: wrong arguments. \n".$usage; + +# DISABLED: always increment +#check if new types have been added since last release. +#If not, then there is nothing to be done. +#read in oldVersions line by line and apply the increment operation +#open TYPES, "$ARGV[3]" or die "Cannot open to $ARGV[3] $!"; + +my $newTypes; + +#We look for the line that contains the number of new types +#while() +#{ +# if (/New and published types/i) +# { +# $_ =~ /=\s*(\d+)/; +# if ( ! defined $1) +# { +# print "\n###$ARGV[3] contains an invalid entry for 'New and published types'. \n\n"; +# exit -1; +# } +# $newTypes = $1; +# } +#} + +#Check if changeTypes contained the line we are looking for +#if (! defined $newTypes) +#{ +# print "\n###$ARGV[3] does not contain entry about the new types ". +# "or we are looking for the wrong string! \n\n"; +# exit -1; +#} + +#if ( $newTypes == 0) +#{ +# print "\nNo new UNO types since las product update.\n"; +# exit 0; +#} +#else +#{ +# print "\nNew UNO types were added since last release. The version will be increased.\n\n"; +#} + +#read in incVersions in a list +my @incVersions = readIncVersions($ARGV[1]); +#print "@incVersions"; + +#read in oldVersions line by line and apply the increment operation +open OLDVERSION, "$ARGV[0]" or die "Cannot open to $ARGV[0] $!"; + +#open file we want to write to +open NEWVERSION, "> $ARGV[2]" or die "Cannot write to $ARGV[2] $!"; + +print NEWVERSION processLine($_, @incVersions) while(); + +close NEWVERSION; +close OLDVERSION; + +exit 0; + +sub processLine($$) +{ + my $line = $_[0]; + #skip empty lines + my $trimmed; + return $line if (length($trimmed = trim($line)) == 0); + #Skip comment symbol: # + return $line if ($trimmed =~ /^#/); + + #Get the left part of '=' + my $i = index($line, "="); + if( $i == -1) + { + print "Error: No '=' found in line:,: \n $line \n"; + exit -1; + } + my $name = substr($line, 0, $i); + $name = trim($name); + #We do not check the names here because the file can contain + #other names, e.g. CLI_URETYPES_POLICY_ASSEMBLY + if (length($name) == 0) { + print "Wrong line in $ARGV[0]\n", $sNameForm; + exit -1; + } + my $value = substr($line, $i + 1); + $value = trim($value); + + #Check if the entry shall be incremented, this information is in the second + #argument + my $found; + for(@incVersions) { + if ($_ eq $name) { + $found = 1; + last; + } + } + if ( ! defined($found)) { + return $line; + } + + #Check if the name represents a version we need to change + if ($name =~ /NEW_VERSION$/) + { + $value = incrementNewVersion($value); + } + elsif ($name =~ /OLD_VERSION$/) + { + $value = incrementOldVersion($value); + } + elsif ($name =~ /POLICY_VERSION$/) + { + $value = incrementPolicyVersion($value); + } + else + { + #other name which we ignore + return $line; + } + return "${name}=${value}\n"; +} + +#The value of a new version has the form x.x.x.x +#We increment the third position from the left. +#Te argument must already be trimmed. +sub incrementNewVersion($) +{ + my @parts = split /\./,$_[0]; + if (scalar @parts != 4) + { + print "Error, no valid version given in $ARGV[0]\n. A 'new version' has four parts."; + exit -1; + } + $parts[2]++; + #build the version string and return + return "$parts[0].$parts[1].$parts[2].$parts[3]"; +} + +#The value of a new version has the form x.x.x.x-x.x.x.x +#We increment the third position of the second part. +#Te argument must already be trimmed. +sub incrementOldVersion($) +{ + my @parts = split /[\.-]/,$_[0]; + if (scalar @parts != 8) + { + print "Error, no valid version given in $ARGV[0]\n. A 'old version' has the form +x.x.x.x-x.x.x.x\n."; + exit -1; + } + $parts[6]++; + return "$parts[0].$parts[1].$parts[2].$parts[3]-$parts[4].$parts[5].$parts[6].$parts[7]"; + return $_[0]; +} + +sub incrementPolicyVersion($) +{ + my @parts = split /\./,$_[0]; + if (scalar @parts != 4) + { + print "Error, no valid version given in $ARGV[0]\n. A 'policy version' has four parts."; + exit -1; + } + $parts[0]++; + #build the version string and return + return "$parts[0].$parts[1].$parts[2].$parts[3]"; +} + + +sub readIncVersions($) +{ + open INC, $_[0] or die "Could not open $_[0] $!"; + my $arg = $_[0]; + my @names; + + while() + { + chomp; + #Skip empty lines + my $line; + if (length($line = trim($_)) == 0) { + next; + } + #Skip comment symbol: # + if ($line =~ /^#/) { + next; + } + if (!checkName($line)) { + print "Wrong entry in file $_[0]\n", $sNameForm; + exit -1; + } + push @names, $line; + } + print "No entries found in $arg\n" if(scalar @names == 0); + return @names; +} + +#The argument must already be trimmed +#returns 1 if ok +sub checkName($) +{ + my $name = $_[0]; + if ( $name !~/NEW_VERSION$|OLD_VERSION$|POLICY_VERSION$/) { + return 0; + } + return 1; +} + +sub trim($) +{ + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} diff --git a/cli_ure/source/scripts/subst_template.pl b/cli_ure/source/scripts/subst_template.pl new file mode 100644 index 0000000000..b3f90fef6d --- /dev/null +++ b/cli_ure/source/scripts/subst_template.pl @@ -0,0 +1,124 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +use warnings; +use strict; +use diagnostics; + +sub trim; +sub readRedirectionValues($); + +my $usage = + "Usage is: \n subst_template.pl configTemplate redirections policyConfig + + configTemplate: The config file which is used for the policy assembly. It + contains place holders for the binding redirection. + + redirections: file containing the values for oldVersion and newVersion tags + which are used in the BindingRedirect element of the config files. + + policyConfig: Name of the file in which we want to write the config file. +"; + + +if (scalar @ARGV < 3) { + print $usage; + exit -1; +} + + +my %redirectionValue = readRedirectionValues($ARGV[1]); +#print "|$_| |$redirectionValue{$_}|\n", for keys %redirectionValue; + + +#Read config file in which we will replace the versions +$/ = undef; +open TEMPLATE, $ARGV[0] or die $!; +my $templ =