diff options
94 files changed, 2732 insertions, 1059 deletions
diff --git a/ChangeLog b/ChangeLog index 784b767dcf9..bf710d6e16c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2004-09-04 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * configure.in: added check for kqueue. Patch from Geoff Norton + in HEAD. + +2004-08-17 Dick Porter <dick@ximian.com> + + * configure.in: Correct intl library for FreeBSD and OpenBSD. + Fixes bug 62884, patch by Tom McLaughlin (tmclaugh@sdf.lonestar.org). + +2004-07-27 John Merryweather Cooper <john_m_cooper@yahoo.com> + * configure.in: Disable __thread test (TLS) for FreeBSD as + it succeeds on FreeBSD 5.x when it should fail. Fix pthread + library detection for FreeBSD 4.x since pthread is embedded + in libc_r on this platform. Fix some typos in my host + regexes for freebsd. + +2004-07-23 Dick Porter <dick@ximian.com> + + * configure.in: Changes for FreeBSD thread support by John + Merryweather Cooper <john_m_cooper@yahoo.com>. + 2004-07-03 Zoltan Varga <vargaz@freemail.hu> * configure.in: Add --with-tls option to replace the misnamed diff --git a/configure.in b/configure.in index 962304855f6..93d6bce8f8c 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ AC_INIT(README) AC_CANONICAL_SYSTEM AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(mono,1.0) +AM_INIT_AUTOMAKE(mono,1.0.3) AM_MAINTAINER_MODE AC_PROG_LN_S @@ -67,7 +67,62 @@ case "$host" in libdl= libgc_threads=no ;; - *-*-*freebsd*|*-*-*openbsd*) +# these flags will work for all versions of -STABLE +# + *-*-*freebsd4*) + platform_win32=no + if test "x$PTHREAD_CFLAGS" = "x"; then + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE -DGC_FREEBSD_THREADS" + libmono_cflags="-D_THREAD_SAFE" + else + CPPFLAGS="$CPPFLAGS $PTHREAD_CFLAGS -DGC_FREEBSD_THREADS" + libmono_cflags="$PTHREAD_CFLAGS" + fi + if test "x$PTHREAD_LIBS" = "x"; then + LDFLAGS="$LDFLAGS -pthread" + libmono_ldflags="-pthread" + else + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" + libmono_ldflags="$PTHREAD_LIBS" + fi + need_link_unlink=yes + AC_DEFINE(PTHREAD_POINTER_ID) + libdl= + libgc_threads=pthreads +# TLS isn't implemented at all on -STABLE + with_nptl=no + with_tls=pthread + ;; +# older versions of -CURRENT will break with these flags but testing +# indicates these older versions won't run Mono anyway +# + *-*-*freebsd5*) + platform_win32=no + if test "x$PTHREAD_CFLAGS" = "x"; then + CPPFLAGS="$CPPFLAGS -DGC_FREEBSD_THREADS" + libmono_cflags= + else + CPPFLAGS="$CPPFLAGS $PTHREAD_CFLAGS -DGC_FREEBSD_THREADS" + libmono_cflags="$PTHREAD_CFLAGS" + fi + if test "x$PTHREAD_LIBS" = "x"; then + LDFLAGS="$LDFLAGS -lpthread" + libmono_ldflags="-lpthread" + else + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" + libmono_ldflags="$PTHREAD_LIBS" + fi + need_link_unlink=yes + AC_DEFINE(PTHREAD_POINTER_ID) + libdl= + libgc_threads=pthreads +# TLS is only partially implemented on -CURRENT (compiler support +# but NOT library support) +# + with_nptl=no + with_tls=pthread + ;; + *-*-*openbsd*) platform_win32=no CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE -DGC_FREEBSD_THREADS" libmono_cflags="-D_THREAD_SAFE" @@ -411,6 +466,7 @@ if test x$platform_win32 = xno; then AC_CHECK_FUNCS(getpwuid_r) AC_CHECK_FUNCS(getresuid) AC_CHECK_FUNCS(setresuid) + AC_CHECK_FUNCS(kqueue) dnl ****************************************************************** dnl *** Check for large file support *** @@ -653,7 +709,17 @@ if test x$platform_win32 = xno; then dnl ***************************** dnl *** Checks for libpthread *** dnl ***************************** - AC_CHECK_LIB(pthread, main, LIBS="$LIBS -lpthread") +# on FreeBSD -STABLE, the pthreads functions all reside in libc_r +# and libpthread does not exist +# + case "${host}" in + *-*-*freebsd4*) + AC_CHECK_LIB(pthread, main, LIBS="$LIBS -pthread") + ;; + *) + AC_CHECK_LIB(pthread, main, LIBS="$LIBS -lpthread") + ;; + esac AC_CHECK_HEADERS(pthread.h) AC_CHECK_FUNCS(pthread_mutex_timedlock) AC_CHECK_FUNCS(pthread_getattr_np pthread_attr_get_np) @@ -1201,6 +1267,14 @@ case "$host" in LIBC="libc.so.12" INTL="libintl.so.0" ;; + *-*-*freebsd*) + LIBC="libc.so" + INTL="libintl.so" + ;; + *-*-*openbsd*) + LIBC="libc.so" + INTL="libintl.so" + ;; esac AC_SUBST(libsuffix) diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/ChangeLog b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/ChangeLog index bcf7dd8b1f8..42df9e1632a 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/ChangeLog +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/ChangeLog @@ -1,3 +1,7 @@ +2004-06-30 Umadevi S <sumadevi@novell.com> + * Tds.cs - In the NextResult method handling TdsPacketSubType. TableName. + + 2004-04-22 Sebastien Pouliot <sebastien@ximian.com> * Tds70.cs: Updated to match changes in Mono.Security.dll. diff --git a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs index 1a917399a3f..e1cf4697ee7 100644 --- a/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs +++ b/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/Tds.cs @@ -293,6 +293,12 @@ namespace Mono.Data.Tds.Protocol { break; case TdsPacketSubType.TableName: + // done = true; + peek = Comm.Peek (); + done = (peek != (byte) TdsPacketSubType.ColumnDetail); + + break; + case TdsPacketSubType.ColumnDetail: done = true; break; default: diff --git a/mcs/class/System.Data/System.Data.Odbc/ChangeLog b/mcs/class/System.Data/System.Data.Odbc/ChangeLog index 91adfefb77e..d8581c1975b 100644 --- a/mcs/class/System.Data/System.Data.Odbc/ChangeLog +++ b/mcs/class/System.Data/System.Data.Odbc/ChangeLog @@ -1,6 +1,3 @@ -2004-07-01 Sureshkumar T (tsureshkumar@novell.com) - * OdbcCommand.cs : fixed reader problem with ExecuteScalar - 2004-06-23 Sureshkumar T (tsureshkumar@novell.com) * OdbcConnection.cs: Fix: Moved env allocation to Open method. Disconnection & freeing handles are done in Close diff --git a/mcs/class/System.Data/System.Data.Odbc/OdbcCommand.cs b/mcs/class/System.Data/System.Data.Odbc/OdbcCommand.cs index e21349af2a9..fe242f3bf8f 100644 --- a/mcs/class/System.Data/System.Data.Odbc/OdbcCommand.cs +++ b/mcs/class/System.Data/System.Data.Odbc/OdbcCommand.cs @@ -342,12 +342,11 @@ namespace System.Data.Odbc public object ExecuteScalar ()
{
- object val = null;
+ object val;
OdbcDataReader reader=ExecuteReader();
try
{
- if (reader.Read ())
- val=reader[0];
+ val=reader[0];
}
finally
{
diff --git a/mcs/class/System.Data/System.Data.SqlClient/ChangeLog b/mcs/class/System.Data/System.Data.SqlClient/ChangeLog index 14efc7d3b1e..5576c7f7c6b 100755 --- a/mcs/class/System.Data/System.Data.SqlClient/ChangeLog +++ b/mcs/class/System.Data/System.Data.SqlClient/ChangeLog @@ -1,3 +1,7 @@ +2004-06-30 Umadevi S <sumadevi@novell.com> + * SqlCommand.cs : In the Execute Method the commandbehavior parameters were ignored correct +these + 2004-06-22 Atsushi Enomoto <atsushi@ximian.com> * SqlCommandBuilder.cs : Avoid cast exception caused by DbNull. diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs index 366b381b54d..21978c14cf2 100644 --- a/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs @@ -268,8 +268,8 @@ namespace System.Data.SqlClient { { TdsMetaParameterCollection parms = Parameters.MetaParameters; if (preparedStatement == null) { - bool schemaOnly = ((CommandBehavior & CommandBehavior.SchemaOnly) > 0); - bool keyInfo = ((CommandBehavior & CommandBehavior.KeyInfo) > 0); + bool schemaOnly = ((behavior & CommandBehavior.SchemaOnly) > 0); + bool keyInfo = ((behavior & CommandBehavior.KeyInfo) > 0); StringBuilder sql1 = new StringBuilder (); StringBuilder sql2 = new StringBuilder (); diff --git a/mcs/class/System.Data/Test/System.Data.Odbc/ChangeLog b/mcs/class/System.Data/Test/System.Data.Odbc/ChangeLog index 8df7a0151f2..bd7b77d4f19 100644 --- a/mcs/class/System.Data/Test/System.Data.Odbc/ChangeLog +++ b/mcs/class/System.Data/Test/System.Data.Odbc/ChangeLog @@ -1,8 +1,3 @@ -2004-07-01 Sureshkumar T <tsureshkumar@novell.com> - * Added test case for OdbcCommand.ExecuteScalar Method - * New files: - OdbcCommandTest.cs - test suite for OdbcCommand class. - 2004-06-23 Sureshkumar T <TSureshkumar@novell.com> * Added test to check whether the OdbcConnection.Close method closes all the handles. diff --git a/mcs/class/System.Data/Test/System.Data.Odbc/OdbcCommandTest.cs b/mcs/class/System.Data/Test/System.Data.Odbc/OdbcCommandTest.cs deleted file mode 100644 index 8b3968c7062..00000000000 --- a/mcs/class/System.Data/Test/System.Data.Odbc/OdbcCommandTest.cs +++ /dev/null @@ -1,70 +0,0 @@ -//
-// OdbcCommandTest.cs - NUnit Test Cases for testing the
-// OdbcCommand class
-//
-// Author:
-// Sureshkumar T (TSureshkumar@novell.com)
-//
-// Copyright (c) 2004 Novell Inc., and the individuals listed
-// on the ChangeLog entries.
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-
-using System;
-using System.Data;
-using System.Data.Odbc;
-
-using NUnit.Framework;
-
-namespace MonoTests.System.Data.Odbc
-{
-
- [TestFixture]
- public class OdbcCommandTest : MySqlOdbcBaseClient
- {
-
- [SetUp]
- public void GetReady () {
- OpenConnection ();
- CreateTestSetup (); // create database & test tables
- }
-
- [TearDown]
- public void Clean () {
- CleanTestSetup (); // clean test database;
- CloseConnection ();
- }
-
- /// <summary>
- /// Test Execute Scalar Method
- /// </summary>
- [Test]
- public void ExecuteScalarTest ()
- {
- OdbcCommand cmd = conn.CreateCommand ();
- string query = "select count(*) from test order by col_int;";
- cmd.CommandText = query;
- object objCount = cmd.ExecuteScalar ();
- Assertion.AssertEquals( "ExecuteScalar does not return int type", 5, Convert.ToInt32(objCount));
- }
- }
-}
diff --git a/mcs/class/System.Drawing/System.Drawing/ChangeLog b/mcs/class/System.Drawing/System.Drawing/ChangeLog index ee4e72e3e57..941f5db4a6c 100644 --- a/mcs/class/System.Drawing/System.Drawing/ChangeLog +++ b/mcs/class/System.Drawing/System.Drawing/ChangeLog @@ -1,7 +1,3 @@ -2004-07-02 Jordi Mas i Hernandez <jordi@ximian.com> - - * gdipFunctions.cs: fixes bug 61050 - 2004-06-24 Sanjay Gupta <gsanjay@novell.com> * ImageAnimator.cs: Rewrote complete implementation. diff --git a/mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs b/mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs index 5244cd50235..8db7223a85c 100644 --- a/mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs +++ b/mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs @@ -1418,11 +1418,7 @@ namespace System.Drawing { public Stream stream; - public GdiPlusStreamHelper (Stream s) - { - stream = s; - stream.Seek(0, SeekOrigin.Begin); - } + public GdiPlusStreamHelper (Stream s) { stream = s; } public int StreamGetBytesImpl (IntPtr buf, int bufsz, bool peek) { diff --git a/mcs/class/System.Web/System.Web.Handlers/ChangeLog b/mcs/class/System.Web/System.Web.Handlers/ChangeLog index 50459bd9024..ebddbc1e4ba 100644 --- a/mcs/class/System.Web/System.Web.Handlers/ChangeLog +++ b/mcs/class/System.Web/System.Web.Handlers/ChangeLog @@ -1,7 +1,3 @@ -2004-07-02 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * TraceHandler.cs: check that trace is enabled or throw. - 2004-06-03 Gonzalo Paniagua Javier <gonzalo@ximian.com> * TraceHandler.cs: Added protected missing members and attributes. diff --git a/mcs/class/System.Web/System.Web.Handlers/TraceHandler.cs b/mcs/class/System.Web/System.Web.Handlers/TraceHandler.cs index 343aa5957a7..33385dbf5fb 100644 --- a/mcs/class/System.Web/System.Web.Handlers/TraceHandler.cs +++ b/mcs/class/System.Web/System.Web.Handlers/TraceHandler.cs @@ -39,27 +39,16 @@ using System.Web.UI.WebControls; namespace System.Web.Handlers { -#if NET_2_0 - [Serializable] -#endif - class TraceNotAvailableException : HttpException - { - public TraceNotAvailableException () : - base ("Trace Error") {} - - internal override string Description { - get { return "Trace.axd is not enabled in the configuration file for this application."; } - } - } - public class TraceHandler : IHttpHandler { void IHttpHandler.ProcessRequest (HttpContext context) { TraceManager manager = HttpRuntime.TraceManager; - if (!manager.Enabled || manager.LocalOnly && !context.Request.IsLocal) { - throw new TraceNotAvailableException (); + if (manager.LocalOnly && !context.Request.IsLocal) { + // Need to figure out the error message that goes here + // but I only have cassini for testing + return; } HtmlTextWriter output = new HtmlTextWriter (context.Response.Output); diff --git a/mcs/class/System.Web/System.Web.UI/ChangeLog b/mcs/class/System.Web/System.Web.UI/ChangeLog index ec02b96092f..07d62fd2c33 100644 --- a/mcs/class/System.Web/System.Web.UI/ChangeLog +++ b/mcs/class/System.Web/System.Web.UI/ChangeLog @@ -1,10 +1,3 @@ -2004-07-02 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * Page.cs: added additional checks for saving/displaying trace data. - - * PageParser.cs: removed checks for trace enabled in configuration - files. - 2004-06-29 Gonzalo Paniagua Javier <gonzalo@ximian.com> * ControlCollection.cs: when clearing the control collection, tell the diff --git a/mcs/class/System.Web/System.Web.UI/Page.cs b/mcs/class/System.Web/System.Web.UI/Page.cs index 79a68d2e233..3887c9c35e0 100755 --- a/mcs/class/System.Web/System.Web.UI/Page.cs +++ b/mcs/class/System.Web/System.Web.UI/Page.cs @@ -769,18 +769,11 @@ public class Page : TemplateControl, IHttpHandler private void RenderTrace (HtmlTextWriter output) { - TraceManager traceManager = HttpRuntime.TraceManager; - - if (Trace.HaveTrace && !Trace.IsEnabled || !Trace.HaveTrace && !traceManager.Enabled) + if (!Trace.IsEnabled) return; Trace.SaveData (); - - if (!Trace.HaveTrace && traceManager.Enabled && !traceManager.PageOutput) - return; - - if (!traceManager.LocalOnly || Context.Request.IsLocal) - Trace.Render (output); + Trace.Render (output); } internal void RaisePostBackEvents () diff --git a/mcs/class/System.Web/System.Web.UI/PageParser.cs b/mcs/class/System.Web/System.Web.UI/PageParser.cs index 571edf2997a..816d83c0bc8 100644 --- a/mcs/class/System.Web/System.Web.UI/PageParser.cs +++ b/mcs/class/System.Web/System.Web.UI/PageParser.cs @@ -199,6 +199,13 @@ namespace System.Web.UI } } + TraceConfig traceConfig = (TraceConfig) Context.GetConfig ("system.web/trace"); + if (traceConfig != null) { + trace = traceConfig.Enabled; + if (trace) + haveTrace = true; + } + string tracestr = GetString (atts, "Trace", null); if (tracestr != null) { haveTrace = true; @@ -220,6 +227,13 @@ namespace System.Web.UI "one of the following values: SortByTime, SortByCategory."); } + if (traceConfig != null) { + if (traceConfig.LocalOnly && !Context.Request.IsLocal) { + haveTrace = false; + trace = false; + } + } + errorPage = GetString (atts, "ErrorPage", null); validateRequest = GetBool (atts, "ValidateRequest", PagesConfig.ValidateRequest); clientTarget = GetString (atts, "ClientTarget", null); diff --git a/mcs/class/System.Web/System.Web/ChangeLog b/mcs/class/System.Web/System.Web/ChangeLog index 7be6f4e6a5f..93cc846bb86 100644 --- a/mcs/class/System.Web/System.Web/ChangeLog +++ b/mcs/class/System.Web/System.Web/ChangeLog @@ -1,8 +1,3 @@ -2004-07-02 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * TraceContext.cs: added internal HaveTrace property whose - value is true when the page has a Trace attribute. - 2004-06-15 Gonzalo Paniagua Javier <gonzalo@ximian.com> * TraceData.cs: fixed <br> output. Closes bug #60181. diff --git a/mcs/class/System.Web/System.Web/TraceContext.cs b/mcs/class/System.Web/System.Web/TraceContext.cs index f939add498b..6d7a7c68608 100644 --- a/mcs/class/System.Web/System.Web/TraceContext.cs +++ b/mcs/class/System.Web/System.Web/TraceContext.cs @@ -42,19 +42,11 @@ namespace System.Web { private TraceMode _Mode;
private TraceData data;
private bool data_saved;
- private bool _haveTrace = false; public TraceContext(HttpContext Context) {
_Context = Context;
_Enabled = false;
}
- - - internal bool HaveTrace { - get { - return _haveTrace; - } - } public bool IsEnabled {
get {
@@ -64,7 +56,6 @@ namespace System.Web { set {
if (value && data == null)
data = new TraceData ();
- _haveTrace = true; _Enabled = value;
}
}
diff --git a/mcs/class/corlib/System.Globalization/ChangeLog b/mcs/class/corlib/System.Globalization/ChangeLog index 95392d51e96..533cc9d4dc7 100644 --- a/mcs/class/corlib/System.Globalization/ChangeLog +++ b/mcs/class/corlib/System.Globalization/ChangeLog @@ -1,3 +1,8 @@ + +Wed Jun 30 17:06:43 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * NumberFormatInfo.cs: workaround for bug 55978. + 2004-06-17 Atsushi Enomoto <atsushi@ximian.com> * DateTimeFormatInfo.cs : check if pattern array is empty or not. Now diff --git a/mcs/class/corlib/System.Globalization/NumberFormatInfo.cs b/mcs/class/corlib/System.Globalization/NumberFormatInfo.cs index 169ad6c2f9e..e884daad5a7 100644 --- a/mcs/class/corlib/System.Globalization/NumberFormatInfo.cs +++ b/mcs/class/corlib/System.Globalization/NumberFormatInfo.cs @@ -851,7 +851,10 @@ throw new Exception ("HERE the value was modified"); public object GetFormat (Type formatType) { - return (formatType == typeof (NumberFormatInfo)) ? this : null; + // work around http://bugzilla.ximian.com/show_bug.cgi?id=55978 + // the comparison fails because formatType likely comes from another domain + //return (formatType == typeof (NumberFormatInfo)) ? this : null; + return this; } public object Clone () diff --git a/mcs/class/corlib/System.Reflection/ChangeLog b/mcs/class/corlib/System.Reflection/ChangeLog index d2fd0f4ac62..8a7945e688e 100644 --- a/mcs/class/corlib/System.Reflection/ChangeLog +++ b/mcs/class/corlib/System.Reflection/ChangeLog @@ -1,7 +1,3 @@ -2004-07-03 Zoltan Varga <vargaz@freemail.hu> - - * Module.cs: Initialize FilterTypeName[IgnoreCase]. Fixes #61048. - 2004-06-17 Gert Driesen <drieseng@users.sourceforge.net> * Pointer.cs: remove serializable attribute to match MS.NET diff --git a/mcs/class/corlib/System.Reflection/Module.cs b/mcs/class/corlib/System.Reflection/Module.cs index d45802fa3b3..01dc55f9be6 100644 --- a/mcs/class/corlib/System.Reflection/Module.cs +++ b/mcs/class/corlib/System.Reflection/Module.cs @@ -55,11 +55,6 @@ namespace System.Reflection { const BindingFlags defaultBindingFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; - static Module () { - FilterTypeName = new TypeFilter (filter_by_type_name); - FilterTypeNameIgnoreCase = new TypeFilter (filter_by_type_name_ignore_case); - } - internal Module () { } ~Module () { @@ -220,22 +215,6 @@ namespace System.Reflection { return new Guid (GetGuidInternal ()); } - private static bool filter_by_type_name (Type m, object filterCriteria) { - string s = (string)filterCriteria; - if (s.EndsWith ("*")) - return m.Name.StartsWith (s.Substring (0, s.Length - 1)); - else - return m.Name == s; - } - - private static bool filter_by_type_name_ignore_case (Type m, object filterCriteria) { - string s = (string)filterCriteria; - if (s.EndsWith ("*")) - return m.Name.ToLower ().StartsWith (s.Substring (0, s.Length - 1).ToLower ()); - else - return String.Compare (m.Name, s, true) == 0; - } - [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern string GetGuidInternal (); diff --git a/mcs/class/corlib/System.Reflection/common.src b/mcs/class/corlib/System.Reflection/common.src new file mode 100644 index 00000000000..022b6768fcc --- /dev/null +++ b/mcs/class/corlib/System.Reflection/common.src @@ -0,0 +1,25 @@ +Assembly.cs +AssemblyNameFlags.cs +BindingFlags.cs +CallingConventions.cs +ConstructorInfo.cs +DefaultMemberAttribute.cs +EventAttributes.cs +EventInfo.cs +FieldAttributes.cs +FieldInfo.cs +ICustomAttributeProvider.cs +MemberFilter.cs +MemberInfo.cs +MemberTypes.cs +MethodAttributes.cs +MethodBase.cs +MethodImplAttributes.cs +MethodInfo.cs +Module.cs +ParameterAttributes.cs +PropertyAttributes.cs +PropertyInfo.cs +ResourceAttributes.cs +ResourceLocation.cs +TypeAttributes.cs diff --git a/mcs/class/corlib/System.Runtime.Remoting/ChangeLog b/mcs/class/corlib/System.Runtime.Remoting/ChangeLog index de3e2e619b5..1fc62be042d 100755 --- a/mcs/class/corlib/System.Runtime.Remoting/ChangeLog +++ b/mcs/class/corlib/System.Runtime.Remoting/ChangeLog @@ -1,10 +1,3 @@ -2004-07-02 Lluis Sanchez Gual <lluis@ximian.com> - - * RemotingConfiguration.cs: Avoid adding "id" and "type" as custom - properties of providers. This fixes bug #60934. - * ServerIdentity.cs, RemotingServices.cs: When disposing an identity, detach - the identity from the object, so it can be safely marshalled again. - 2004-06-15 Gert Driesen <drieseng@users.sourceforge.net> * RemotingTimeoutException.cs: added missing serialization ctor diff --git a/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs b/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs index 2cbe62dff51..204bc6b4368 100644 --- a/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs +++ b/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs @@ -721,9 +721,9 @@ namespace System.Runtime.Remoting if (at == "id" && isTemplate) prov.Id = val; - else if (at == "type") + if (at == "type") prov.Type = val; - else if (at == "ref" && !isTemplate) + if (at == "ref" && !isTemplate) prov.Ref = val; else prov.CustomProperties.Add (at, val); diff --git a/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs b/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs index 475164d981a..aa694cbb3b6 100644 --- a/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs +++ b/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs @@ -159,10 +159,8 @@ namespace System.Runtime.Remoting else throw new ArgumentException ("The obj parameter is a proxy."); } - else { + else identity = obj.ObjectIdentity; - obj.ObjectIdentity = null; - } if (identity == null || !identity.IsConnected) return false; diff --git a/mcs/class/corlib/System.Runtime.Remoting/ServerIdentity.cs b/mcs/class/corlib/System.Runtime.Remoting/ServerIdentity.cs index 72c025121d0..f5ed96a066b 100644 --- a/mcs/class/corlib/System.Runtime.Remoting/ServerIdentity.cs +++ b/mcs/class/corlib/System.Runtime.Remoting/ServerIdentity.cs @@ -136,13 +136,7 @@ namespace System.Runtime.Remoting protected void DisposeServerObject() { - // Detach identity from server object to avoid problems if the - // object is marshalled again. - - if (_serverObject != null) { - _serverObject.ObjectIdentity = null; - _serverObject = null; - } + _serverObject = null; } } diff --git a/mcs/class/corlib/Test/System.Reflection/ChangeLog b/mcs/class/corlib/Test/System.Reflection/ChangeLog index fd367c75537..2c5110a6ee3 100644 --- a/mcs/class/corlib/Test/System.Reflection/ChangeLog +++ b/mcs/class/corlib/Test/System.Reflection/ChangeLog @@ -1,7 +1,3 @@ -2004-07-03 Zoltan Varga <vargaz@freemail.hu> - - * ModuleTest.cs: New tests for FindTypes. - 2004-06-10 Lluis Sanchez <lluis@ximian.com> * AssemblyNameTest.cs: AssertEqualsByteArrays(): don't crash if arrays are diff --git a/mcs/errors/cs0502.cs b/mcs/errors/cs0502.cs index e2232ec0c29..b589cba2f75 100644 --- a/mcs/errors/cs0502.cs +++ b/mcs/errors/cs0502.cs @@ -1,6 +1,5 @@ -// cs0502.cs: The class 'Sample' is abstract and sealed
-// Line: 4
-
-abstract sealed class Sample {
-}
-
+// cs0502.cs: 'Sample' cannot be both abstract and sealed +// Line: 4 + +abstract sealed class Sample { +} diff --git a/mono/dis/get.c b/mono/dis/get.c index 43845cd6c19..22dea4fa32a 100644 --- a/mono/dis/get.c +++ b/mono/dis/get.c @@ -197,6 +197,7 @@ get_typespec (MonoImage *m, guint32 idx) if (s) g_string_append (res, s); } + g_string_append (res, "*"); break; case MONO_TYPE_FNPTR: diff --git a/mono/io-layer/ChangeLog b/mono/io-layer/ChangeLog index 5b19c8ceadf..5178d3ac7bc 100644 --- a/mono/io-layer/ChangeLog +++ b/mono/io-layer/ChangeLog @@ -1,3 +1,116 @@ +2004-09-28 Dick Porter <dick@ximian.com> + + * io.c (pipe_close_private): Fix one small typo in the last change + that totally hosed process creation with redirected pipes. + +2004-09-24 Dick Porter <dick@ximian.com> + + * wapi-private.h: + * sockets.c: + * socket-private.h: + * io.c: + * io-private.h: + * handles-private.h: Cope when a file descriptor is reused while + the handle that thought it owned it is still referenced, instead + of asserting. Probably fixes bug 66479, though we've been unable + to reproduce it. + +2004-09-09 Dick Porter <dick@ximian.com> + + * error.c: + * io.c: Set error codes everywhere. + +2004-09-06 Dick Porter <dick@ximian.com> + + * handles.c (_wapi_handle_unref): Reset the private record's type + (_wapi_handle_process_fork): Fix long-standing bug in checking + handle return values. Also do the required bookkeeping with the + new process's handles. + + * daemon.c: When creating a new process's handles, check whether + the shared space needs to be increased + +2004-08-19 Dick Porter <dick@ximian.com> + + * handles.c (_wapi_handle_count_signalled_handles): Fix thinko + introduced with the fd offset stuff: unlock handles properly when + backing off. Fixes the monologue hang at exit. + +2004-08-18 Dick Porter <dick@ximian.com> + + * sockets.c: + * io.c: Check that new fds fit in the table, return error if not + + * daemon.c (_wapi_daemon_main): + * handles.c (shared_init): Have all processes agree on a size for + the fd table. + +2004-08-17 Dick Porter <dick@ximian.com> + + * daemon.c (process_new): + * handles.c (_wapi_handle_new_internal): Cope when the space + reserved for file descriptors is larger than the shared segment + size. Fixes the crash reported when running mono under gdb on + macosx. + +2004-08-16 Dick Porter <dick@ximian.com> + + * sockets.c: + * io.c: + * handles-private.h (_wapi_handle_fd_offset_to_handle): Improve + error checking with passed-in file descriptors. + +2004-08-11 Dick Porter <dick@ximian.com> + + * sockets.c: + * io.c: Returned handle values are the file descriptor the handle + encapsulates + + * handles.c: + * handles-private.h: + * daemon.c: Reserve the range of handles that can have the same + values as file descriptors. These won't be used, but the values + will be used as file, console, pipe or socket handles. The fd to + handle mapping is done internally and is invisible to users. + Fixes bug 61828. + + * wapi-private.h (_WAPI_HANDLE_VERSION): Increment, because we now + reserve a chunk of handle space. + +2004-07-22 Dick Porter <dick@ximian.com> + + * timed-thread.c: + * threads.c: Move the destruction of the internal thread data to + after the thread has been joined. Fixes bug 61418. + +2004-07-14 Dick Porter <dick@ximian.com> + + * wait.c (test_and_own): When not waiting for all handles to + become signalled, only own and return the lowest. All the + documentation suggests that the old way was correct, but + experimentation shows it actually works like this. Patch by + Sébastien Robitaille + (sebastien.robitaille@croesus.com), fixes bug 61511. + +2004-07-08 Dick Porter <dick@ximian.com> + + * io.c (file_seek): If there is a high 32bit offset part, make + sure the low part isn't sign-extended. Set error codes when + returning failure. Fixes bug 61131. + +2004-07-06 Dick Porter <dick@ximian.com> + + * io.c (file_setfiletime): Check for underflow when converting to + time_t values. Set error codes when returning failure. Fixes bug + 60970. + +2004-07-05 Dick Porter <dick@ximian.com> + + * mutexes.c (mutex_ops_init): Make the named mutex mutex sharable. + + * daemon.c (unref_handle): Only destroy a handle if all processes + have released it, not just the current one. Fixes bug 60887. + 2004-06-24 Dick Porter <dick@ximian.com> * mutexes.c: Indicate when a named mutex was reused diff --git a/mono/io-layer/daemon.c b/mono/io-layer/daemon.c index 746fba49d17..e2eca91b3eb 100644 --- a/mono/io-layer/daemon.c +++ b/mono/io-layer/daemon.c @@ -340,16 +340,14 @@ static gboolean unref_handle (ChannelData *channel_data, guint32 handle) channel_data->open_handles[handle]); #endif - if(channel_data->open_handles[handle]==0) { - /* This client has released the handle */ - destroy=TRUE; - } - - if(_wapi_shared_data[segment]->handles[idx].ref==0) { + if (_wapi_shared_data[segment]->handles[idx].ref == 0) { gboolean was_file; dev_t device = 0; ino_t inode = 0; + /* This client has released the handle */ + destroy=TRUE; + if (channel_data->open_handles[handle]!=0) { g_warning (G_GNUC_PRETTY_FUNCTION ": per-process open_handles mismatch, set to %d, should be 0", channel_data->open_handles[handle]); @@ -832,23 +830,11 @@ static void send_reply (GIOChannel *channel, WapiHandleResponse *resp) _wapi_daemon_response (g_io_channel_unix_get_fd (channel), resp); } -/* - * process_new: - * @channel: The client making the request - * @channel_data: Our data for this channel - * @type: type to init handle to - * - * Find a free handle and initialize it to 'type', increase refcnt and - * send back a reply to the client. - */ -static void process_new (GIOChannel *channel, ChannelData *channel_data, - WapiHandleType type) +static guint32 new_handle_with_shared_check (WapiHandleType type) { - guint32 handle; - WapiHandleResponse resp={0}; - - handle=_wapi_handle_new_internal (type); - if(handle==0) { + guint32 handle = 0; + + while ((handle = _wapi_handle_new_internal (type)) == 0) { /* Try and allocate a new shared segment, and have * another go */ @@ -873,15 +859,34 @@ static void process_new (GIOChannel *channel, ChannelData *channel_data, channels[i].open_handles=_wapi_g_renew0 (channels[i].open_handles, old_len, new_len); } } - - handle=_wapi_handle_new_internal (type); } else { /* Map failed. Just return 0 meaning "out of * handles" */ + break; } } + return(handle); +} + +/* + * process_new: + * @channel: The client making the request + * @channel_data: Our data for this channel + * @type: type to init handle to + * + * Find a free handle and initialize it to 'type', increase refcnt and + * send back a reply to the client. + */ +static void process_new (GIOChannel *channel, ChannelData *channel_data, + WapiHandleType type) +{ + guint32 handle; + WapiHandleResponse resp={0}; + + handle = new_handle_with_shared_check (type); + /* handle might still be set to 0. This is handled at the * client end */ @@ -1066,11 +1071,11 @@ static void process_process_fork (GIOChannel *channel, ChannelData *channel_data * client must check if either handle is 0 and take * appropriate error handling action. */ - process_handle=_wapi_handle_new_internal (WAPI_HANDLE_PROCESS); + process_handle = new_handle_with_shared_check (WAPI_HANDLE_PROCESS); ref_handle (daemon_channel_data, process_handle); ref_handle (channel_data, process_handle); - thread_handle=_wapi_handle_new_internal (WAPI_HANDLE_THREAD); + thread_handle = new_handle_with_shared_check (WAPI_HANDLE_THREAD); ref_handle (daemon_channel_data, thread_handle); ref_handle (channel_data, thread_handle); @@ -1248,7 +1253,7 @@ static void process_process_fork (GIOChannel *channel, ChannelData *channel_data resp.u.process_fork.pid=pid; } - + resp.u.process_fork.process_handle=process_handle; resp.u.process_fork.thread_handle=thread_handle; @@ -1493,6 +1498,9 @@ void _wapi_daemon_main(gpointer data, gpointer scratch) /* Note that we've got the starting segment already */ _wapi_shared_data[0]->num_segments=1; _wapi_shm_mapped_segments=1; + + _wapi_fd_offset_table_size=getdtablesize (); + _wapi_shared_data[0]->fd_offset_table_size = _wapi_fd_offset_table_size; startup (); diff --git a/mono/io-layer/error.c b/mono/io-layer/error.c index ee6dd56c96e..b167c1e9999 100644 --- a/mono/io-layer/error.c +++ b/mono/io-layer/error.c @@ -194,6 +194,14 @@ _wapi_get_win32_file_error (gint err) ret = ERROR_NOT_SUPPORTED; break; + case EBADF: + ret = ERROR_INVALID_HANDLE; + break; + + case EIO: + ret = ERROR_INVALID_HANDLE; + break; + default: g_message ("Unknown errno: %s\n", strerror (err)); ret = ERROR_GEN_FAILURE; diff --git a/mono/io-layer/handles-private.h b/mono/io-layer/handles-private.h index 674e01384b9..ad03546705c 100644 --- a/mono/io-layer/handles-private.h +++ b/mono/io-layer/handles-private.h @@ -28,6 +28,9 @@ extern struct _WapiHandlePrivate_list **_wapi_private_data; extern pthread_mutex_t _wapi_shared_mutex; extern guint32 _wapi_shm_mapped_segments; +extern guint32 _wapi_fd_offset_table_size; +extern gpointer *_wapi_fd_offset_table; + extern guint32 _wapi_handle_new_internal (WapiHandleType type); extern gpointer _wapi_handle_new (WapiHandleType type); extern gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type, @@ -220,11 +223,38 @@ static inline guint32 _wapi_handle_index (guint32 segment, guint32 idx) return((segment*_WAPI_HANDLES_PER_SEGMENT)+idx); } +static inline gpointer _wapi_handle_fd_offset_to_handle (gpointer fd_handle) +{ + int fd = GPOINTER_TO_INT (fd_handle); + gpointer handle; + + if (fd >= _wapi_fd_offset_table_size) { + return(NULL); + } + + handle = _wapi_fd_offset_table[fd]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + return(NULL); + } + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": Returning fd offset %d of %p", fd, + handle); +#endif + + return(handle); +} + static inline WapiHandleType _wapi_handle_type (gpointer handle) { guint32 idx; guint32 segment; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); if(segment>=_wapi_shm_mapped_segments) @@ -233,6 +263,48 @@ static inline WapiHandleType _wapi_handle_type (gpointer handle) return(_wapi_handle_get_shared_segment (segment)->handles[idx].type); } +static inline void _wapi_handle_fd_offset_store (int fd, gpointer handle) +{ + g_assert (fd < _wapi_fd_offset_table_size); + + if (_wapi_fd_offset_table[fd] != NULL && handle != NULL) { + gpointer oldhandle = _wapi_fd_offset_table[fd]; + struct _WapiHandlePrivate *private_handle; + guint32 idx; + guint32 segment; + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION + ": Reassigning fd offset %d from %p", fd, + oldhandle); +#endif + + /* The WapiFDMapped struct at the head of the private + * handle data means we don't need to do a full + * lookup, and we don't need to know the handle type. + */ + g_assert (_wapi_handle_type (oldhandle) == WAPI_HANDLE_FILE || + _wapi_handle_type (oldhandle) == WAPI_HANDLE_CONSOLE || + _wapi_handle_type (oldhandle) == WAPI_HANDLE_PIPE || + _wapi_handle_type (oldhandle) == WAPI_HANDLE_SOCKET); + + _wapi_handle_segment (oldhandle, &segment, &idx); + _wapi_handle_ensure_mapped (segment); + + private_handle=&_wapi_handle_get_private_segment(segment)->handles[idx]; + ((WapiFDMapped *)(&private_handle->u))->assigned = FALSE; + } + + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size || handle==NULL); + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": Assigning fd offset %d to %p", fd, + handle); +#endif + + _wapi_fd_offset_table[fd]=handle; +} + static inline void _wapi_handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast) @@ -242,6 +314,8 @@ static inline void _wapi_handle_set_signal_state (gpointer handle, struct _WapiHandleShared *shared_handle; int thr_ret; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx]; @@ -317,6 +391,8 @@ static inline gboolean _wapi_handle_issignalled (gpointer handle) guint32 idx; guint32 segment; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); return(_wapi_handle_get_shared_segment (segment)->handles[idx].signalled); @@ -352,6 +428,8 @@ static inline int _wapi_handle_lock_handle (gpointer handle) guint32 idx; guint32 segment; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle); #endif @@ -369,6 +447,8 @@ static inline int _wapi_handle_unlock_handle (gpointer handle) guint32 segment; int ret; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle); #endif diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c index 769235fe76d..a1c3dde13ef 100644 --- a/mono/io-layer/handles.c +++ b/mono/io-layer/handles.c @@ -77,6 +77,9 @@ pthread_mutex_t _wapi_shared_mutex=PTHREAD_MUTEX_INITIALIZER; */ guint32 _wapi_shm_mapped_segments; +guint32 _wapi_fd_offset_table_size; +gpointer *_wapi_fd_offset_table=NULL; + static void shared_init (void) { struct sockaddr_un shared_socket_address; @@ -86,7 +89,7 @@ static void shared_init (void) _wapi_shared_data=g_new0 (struct _WapiHandleShared_list *, 1); _wapi_private_data=g_new0 (struct _WapiHandlePrivate_list *, 1); - + attach_again: #ifndef DISABLE_SHARED_HANDLES @@ -146,6 +149,9 @@ attach_again: goto attach_again; } + } else { + _wapi_fd_offset_table_size = _wapi_shared_data[0]->fd_offset_table_size; + _wapi_fd_offset_table=g_new0 (gpointer, _wapi_fd_offset_table_size); } } @@ -158,6 +164,10 @@ attach_again: _wapi_shared_data[0]->num_segments=1; _wapi_shared_scratch=g_new0 (struct _WapiHandleScratch, 1); + + _wapi_fd_offset_table_size=getdtablesize (); + _wapi_fd_offset_table=g_new0 (gpointer, + _wapi_fd_offset_table_size); } _wapi_private_data[0]=g_new0 (struct _WapiHandlePrivate_list, 1); _wapi_shm_mapped_segments=1; @@ -240,6 +250,7 @@ guint32 _wapi_handle_new_internal (WapiHandleType type) guint32 i, j; static guint32 last=1; int thr_ret; + guint32 num_segments = _wapi_handle_get_shared_segment (0)->num_segments; /* A linear scan should be fast enough. Start from the last * allocation, assuming that handles are allocated more often @@ -250,8 +261,7 @@ guint32 _wapi_handle_new_internal (WapiHandleType type) #endif again: _wapi_handle_segment (GUINT_TO_POINTER (last), &segment, &idx); - for(i=segment; i<_wapi_handle_get_shared_segment (0)->num_segments; - i++) { + for(i=segment; i < num_segments; i++) { if(i!=segment) { idx=0; } @@ -259,8 +269,20 @@ again: for(j=idx; j<_WAPI_HANDLES_PER_SEGMENT; j++) { struct _WapiHandleShared *shared; - /* Make sure we dont try and assign handle 0 */ - if (i==0 && j==0) { + /* Make sure we dont try and assign the + * handles that would clash with fds + */ + if ((i * _WAPI_HANDLES_PER_SEGMENT + j) < _wapi_fd_offset_table_size) { + i = _wapi_fd_offset_table_size / _WAPI_HANDLES_PER_SEGMENT; + j = _wapi_fd_offset_table_size - (i * _WAPI_HANDLES_PER_SEGMENT); + + if (i >= num_segments) { + /* Need to get the caller to + * add more shared segments + */ + return(0); + } + continue; } @@ -314,7 +336,7 @@ gpointer _wapi_handle_new (WapiHandleType type) int thr_ret; mono_once (&shared_init_once, shared_init); - + again: if(shared==TRUE) { new.type=WapiHandleRequestType_New; @@ -336,8 +358,7 @@ again: thr_ret = pthread_mutex_lock (&scan_mutex); g_assert (thr_ret == 0); - handle_idx=_wapi_handle_new_internal (type); - if(handle_idx==0) { + while ((handle_idx = _wapi_handle_new_internal (type)) == 0) { /* Try and get a new segment, and have another go */ segment=_wapi_handle_get_shared_segment (0)->num_segments; _wapi_handle_ensure_mapped (segment); @@ -345,7 +366,6 @@ again: if(_wapi_handle_get_shared_segment (segment)!=NULL) { /* Got a new segment */ _wapi_handle_get_shared_segment (0)->num_segments++; - handle_idx=_wapi_handle_new_internal (type); } else { /* Map failed. Just return 0 meaning * "out of handles" @@ -361,6 +381,9 @@ again: pthread_cleanup_pop (0); } + /* Make sure we left the space for fd mappings */ + g_assert (handle_idx >= _wapi_fd_offset_table_size); + if(handle_idx==0) { g_warning (G_GNUC_PRETTY_FUNCTION ": Ran out of handles!"); @@ -414,6 +437,8 @@ gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type, guint32 idx; guint32 segment; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); _wapi_handle_ensure_mapped (segment); @@ -592,6 +617,8 @@ gpointer _wapi_search_handle_namespace (WapiHandleType type, void _wapi_handle_ref (gpointer handle) { + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + if(shared==TRUE) { WapiHandleRequest req={0}; WapiHandleResponse resp={0}; @@ -628,6 +655,8 @@ void _wapi_handle_unref (gpointer handle) gboolean destroy = FALSE; int thr_ret; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); if(shared==TRUE) { @@ -676,6 +705,7 @@ void _wapi_handle_unref (gpointer handle) _wapi_handle_ops_close_private (handle); _wapi_handle_get_shared_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED; + _wapi_handle_get_private_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED; /* Destroy the mutex and cond var. We hope nobody * tried to grab them between the handle unlock and @@ -1180,6 +1210,10 @@ gboolean _wapi_handle_test_capabilities (gpointer handle, guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1197,6 +1231,10 @@ void _wapi_handle_ops_close_shared (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1211,6 +1249,10 @@ void _wapi_handle_ops_close_private (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1232,6 +1274,10 @@ void _wapi_handle_ops_signal (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1246,6 +1292,10 @@ void _wapi_handle_ops_own (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1260,6 +1310,10 @@ gboolean _wapi_handle_ops_isowned (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1284,6 +1338,14 @@ gboolean _wapi_handle_ops_isowned (gpointer handle) */ gboolean CloseHandle(gpointer handle) { + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + + if (handle == NULL) { + return(FALSE); + } + _wapi_handle_unref (handle); return(TRUE); @@ -1303,12 +1365,17 @@ gboolean _wapi_handle_count_signalled_handles (guint32 numhandles, again: for(i=0; i<numhandles; i++) { guint32 idx, segment; + gpointer handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } - _wapi_handle_segment (handles[i], &segment, &idx); + _wapi_handle_segment (handle, &segment, &idx); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": attempting to lock %p", - handles[i]); + handle); #endif ret=mono_mutex_trylock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex); @@ -1317,11 +1384,17 @@ again: struct timespec sleepytime; #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION ": attempt failed for %p", handles[i]); + g_message (G_GNUC_PRETTY_FUNCTION ": attempt failed for %p: %s", handle, strerror (ret)); #endif while(i--) { - _wapi_handle_segment (handles[i], &segment, &idx); + handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + + _wapi_handle_segment (handle, &segment, &idx); thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex); g_assert (thr_ret == 0); } @@ -1359,24 +1432,29 @@ again: for(i=0; i<numhandles; i++) { guint32 idx, segment; - - _wapi_handle_ref (handles[i]); + gpointer handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + + _wapi_handle_ref (handle); - _wapi_handle_segment (handles[i], &segment, &idx); + _wapi_handle_segment (handle, &segment, &idx); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": Checking handle %p", - handles[i]); + handle); #endif - if(((_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_OWN)==TRUE) && - (_wapi_handle_ops_isowned (handles[i])==TRUE)) || + if(((_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_OWN)==TRUE) && + (_wapi_handle_ops_isowned (handle)==TRUE)) || (_wapi_handle_get_shared_segment (segment)->handles[idx].signalled==TRUE)) { count++; #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION - ": Handle %p signalled", handles[i]); + ": Handle %p signalled", handle); #endif if(*lowest>i) { *lowest=i; @@ -1412,18 +1490,23 @@ void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles) for(i=0; i<numhandles; i++) { guint32 idx, segment; - - _wapi_handle_segment (handles[i], &segment, &idx); + gpointer handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + + _wapi_handle_segment (handle, &segment, &idx); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", - handles[i]); + handle); #endif thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex); g_assert (thr_ret == 0); - _wapi_handle_unref (handles[i]); + _wapi_handle_unref (handle); } } @@ -1495,6 +1578,10 @@ int _wapi_handle_wait_signal_handle (gpointer handle) #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1 guint32 idx, segment; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); return(mono_cond_wait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, @@ -1504,6 +1591,10 @@ int _wapi_handle_wait_signal_handle (gpointer handle) struct timespec fake_timeout; int ret; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); _wapi_calc_timeout (&fake_timeout, 100); @@ -1524,6 +1615,10 @@ int _wapi_handle_timedwait_signal_handle (gpointer handle, #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1 guint32 idx, segment; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); return(mono_cond_timedwait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, @@ -1534,6 +1629,10 @@ int _wapi_handle_timedwait_signal_handle (gpointer handle, struct timespec fake_timeout; int ret; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); _wapi_calc_timeout (&fake_timeout, 100); @@ -1609,9 +1708,26 @@ gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env, guint32 dir, * exec_errno will be set, and the handle will be * signalled immediately. */ - if(process_handle==0 || thread_handle==0) { + if(*process_handle==0 || *thread_handle==0) { return(FALSE); } else { + /* This call returns new handles, so we need to do + * a little bookkeeping + */ + if (_wapi_private_data != NULL) { + guint32 segment, idx; + + _wapi_handle_segment (*process_handle, + &segment, &idx); + _wapi_handle_ensure_mapped (segment); + _wapi_handle_get_private_segment (segment)->handles[idx].type = WAPI_HANDLE_PROCESS; + + _wapi_handle_segment (*thread_handle, + &segment, &idx); + _wapi_handle_ensure_mapped (segment); + _wapi_handle_get_private_segment (segment)->handles[idx].type = WAPI_HANDLE_THREAD; + } + return(TRUE); } } else { diff --git a/mono/io-layer/io-private.h b/mono/io-layer/io-private.h index 374be059956..0fd2b4a7d4b 100644 --- a/mono/io-layer/io-private.h +++ b/mono/io-layer/io-private.h @@ -34,13 +34,9 @@ struct _WapiHandle_file ino_t inode; }; -/* The boolean is for distinguishing between a zeroed struct being not - * as yet assigned, and one containing a valid fd 0 - */ struct _WapiHandlePrivate_file { - int fd; - gboolean assigned; + WapiFDMapped fd_mapped; gboolean async; WapiOverlappedCB callback; }; diff --git a/mono/io-layer/io.c b/mono/io-layer/io.c index e0436186ee0..21708612564 100644 --- a/mono/io-layer/io.c +++ b/mono/io-layer/io.c @@ -236,6 +236,7 @@ static void file_close_shared (gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return; } @@ -263,15 +264,21 @@ static void file_close_private (gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return; } + if (file_private_handle->fd_mapped.assigned) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": closing file handle %p with fd %d", - handle, file_private_handle->fd); + g_message(G_GNUC_PRETTY_FUNCTION ": closing file handle %p with fd %d", + handle, file_private_handle->fd_mapped.fd); #endif - close(file_private_handle->fd); + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (file_private_handle->fd_mapped.fd, NULL); + + close(file_private_handle->fd_mapped.fd); + } } static WapiFileType file_getfiletype(void) @@ -326,6 +333,12 @@ static gboolean file_read(gpointer handle, gpointer buffer, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -336,15 +349,17 @@ static gboolean file_read(gpointer handle, gpointer buffer, if(!(file_handle->fileaccess&GENERIC_READ) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } if (file_private_handle->async == FALSE) { do { - ret=read(file_private_handle->fd, buffer, numbytes); + ret=read(file_private_handle->fd_mapped.fd, buffer, + numbytes); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -354,7 +369,8 @@ static gboolean file_read(gpointer handle, gpointer buffer, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": read of handle %p fd %d error: %s", handle, - file_private_handle->fd, strerror(err)); + file_private_handle->fd_mapped.fd, + strerror(err)); #endif SetLastError (_wapi_get_win32_file_error (err)); return(FALSE); @@ -377,7 +393,7 @@ static gboolean file_read(gpointer handle, gpointer buffer, } { - int fd = file_private_handle->fd; + int fd = file_private_handle->fd_mapped.fd; struct aiocb *aio; int result; notifier_data_t *ndata; @@ -441,6 +457,12 @@ static gboolean file_write(gpointer handle, gconstpointer buffer, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -451,9 +473,10 @@ static gboolean file_write(gpointer handle, gconstpointer buffer, if(!(file_handle->fileaccess&GENERIC_WRITE) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } @@ -464,37 +487,40 @@ static gboolean file_write(gpointer handle, gconstpointer buffer, * because we only do advisory locking on POSIX * systems */ - current_pos = lseek (file_private_handle->fd, (off_t)0, - SEEK_CUR); + current_pos = lseek (file_private_handle->fd_mapped.fd, + (off_t)0, SEEK_CUR); if (current_pos == -1) { #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d lseek failed: %s", handle, file_private_handle->fd, strerror (errno)); + g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d lseek failed: %s", handle, file_private_handle->fd_mapped.fd, strerror (errno)); #endif _wapi_set_last_error_from_errno (); return(FALSE); } - if (_wapi_lock_file_region (file_private_handle->fd, + if (_wapi_lock_file_region (file_private_handle->fd_mapped.fd, current_pos, numbytes) == FALSE) { /* The error has already been set */ return(FALSE); } do { - ret=write(file_private_handle->fd, buffer, numbytes); + ret=write(file_private_handle->fd_mapped.fd, buffer, + numbytes); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); - _wapi_unlock_file_region (file_private_handle->fd, current_pos, - numbytes); + _wapi_unlock_file_region (file_private_handle->fd_mapped.fd, + current_pos, numbytes); if(ret==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": write of handle %p fd %d error: %s", handle, - file_private_handle->fd, strerror(errno)); + file_private_handle->fd_mapped.fd, + strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } if(byteswritten!=NULL) { @@ -513,7 +539,7 @@ static gboolean file_write(gpointer handle, gconstpointer buffer, } { - int fd = file_private_handle->fd; + int fd = file_private_handle->fd_mapped.fd; struct aiocb *aio; int result; notifier_data_t *ndata; @@ -575,26 +601,34 @@ static gboolean file_flush(gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } if(!(file_handle->fileaccess&GENERIC_WRITE) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } - ret=fsync(file_private_handle->fd); + ret=fsync(file_private_handle->fd_mapped.fd); if (ret==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION - ": write of handle %p fd %d error: %s", handle, - file_private_handle->fd, strerror(errno)); + ": fsync of handle %p fd %d error: %s", handle, + file_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } @@ -617,16 +651,23 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return(INVALID_SET_FILE_POINTER); } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } if(!(file_handle->fileaccess&GENERIC_READ) && !(file_handle->fileaccess&GENERIC_WRITE) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(INVALID_SET_FILE_POINTER); } @@ -646,6 +687,7 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, method); #endif + SetLastError (ERROR_INVALID_PARAMETER); return(INVALID_SET_FILE_POINTER); } @@ -658,7 +700,7 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, movedistance); #endif } else { - offset=((gint64) *highmovedistance << 32) | movedistance; + offset=((gint64) *highmovedistance << 32) | (unsigned long)movedistance; #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance); @@ -672,22 +714,24 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, #ifdef HAVE_LARGE_FILE_SUPPORT g_message(G_GNUC_PRETTY_FUNCTION ": moving handle %p fd %d by %lld bytes from %d", handle, - file_private_handle->fd, offset, whence); + file_private_handle->fd_mapped.fd, offset, whence); #else g_message(G_GNUC_PRETTY_FUNCTION ": moving handle %p fd %d by %ld bytes from %d", handle, - file_private_handle->fd, offset, whence); + file_private_handle->fd_mapped.fd, offset, whence); #endif #endif - newpos=lseek(file_private_handle->fd, offset, whence); + newpos=lseek(file_private_handle->fd_mapped.fd, offset, whence); if(newpos==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": lseek on handle %p fd %d returned error %s", - handle, file_private_handle->fd, strerror(errno)); + handle, file_private_handle->fd_mapped.fd, + strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(INVALID_SET_FILE_POINTER); } @@ -715,7 +759,7 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": move of handle %p fd %d returning %d/%d", handle, - file_private_handle->fd, ret, + file_private_handle->fd_mapped.fd, ret, highmovedistance==NULL?0:*highmovedistance); #endif @@ -737,15 +781,22 @@ static gboolean file_setendoffile(gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } if(!(file_handle->fileaccess&GENERIC_WRITE) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } @@ -755,33 +806,35 @@ static gboolean file_setendoffile(gpointer handle) * than the length, truncate the file. */ - ret=fstat(file_private_handle->fd, &statbuf); + ret=fstat(file_private_handle->fd_mapped.fd, &statbuf); if(ret==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d fstat failed: %s", handle, - file_private_handle->fd, strerror(errno)); + file_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } size=statbuf.st_size; - pos=lseek(file_private_handle->fd, (off_t)0, SEEK_CUR); + pos=lseek(file_private_handle->fd_mapped.fd, (off_t)0, SEEK_CUR); if(pos==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d lseek failed: %s", handle, - file_private_handle->fd, strerror(errno)); + file_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } if(pos>size) { /* extend */ do { - ret=write(file_private_handle->fd, "", 1); + ret=write(file_private_handle->fd_mapped.fd, "", 1); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -789,10 +842,11 @@ static gboolean file_setendoffile(gpointer handle) #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d extend write failed: %s", - handle, file_private_handle->fd, + handle, file_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } } @@ -801,7 +855,7 @@ static gboolean file_setendoffile(gpointer handle) * byte to the end of the file */ do { - ret=ftruncate(file_private_handle->fd, pos); + ret=ftruncate(file_private_handle->fd_mapped.fd, pos); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -809,9 +863,10 @@ static gboolean file_setendoffile(gpointer handle) #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d ftruncate failed: %s", handle, - file_private_handle->fd, strerror(errno)); + file_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } @@ -833,27 +888,35 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return(INVALID_FILE_SIZE); } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } if(!(file_handle->fileaccess&GENERIC_READ) && !(file_handle->fileaccess&GENERIC_WRITE) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(INVALID_FILE_SIZE); } - ret=fstat(file_private_handle->fd, &statbuf); + ret=fstat(file_private_handle->fd_mapped.fd, &statbuf); if(ret==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d fstat failed: %s", handle, - file_private_handle->fd, strerror(errno)); + file_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(INVALID_FILE_SIZE); } @@ -895,26 +958,34 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } if(!(file_handle->fileaccess&GENERIC_READ) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } - ret=fstat(file_private_handle->fd, &statbuf); + ret=fstat(file_private_handle->fd_mapped.fd, &statbuf); if(ret==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d fstat failed: %s", handle, - file_private_handle->fd, strerror(errno)); + file_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } @@ -986,15 +1057,22 @@ static gboolean file_setfiletime(gpointer handle, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } if(!(file_handle->fileaccess&GENERIC_WRITE) && !(file_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } @@ -1002,29 +1080,43 @@ static gboolean file_setfiletime(gpointer handle, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d unknown filename", handle, - file_private_handle->fd); + file_private_handle->fd_mapped.fd); #endif + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } /* Get the current times, so we can put the same times back in * the event that one of the FileTime structs is NULL */ - ret=fstat(file_private_handle->fd, &statbuf); + ret=fstat(file_private_handle->fd_mapped.fd, &statbuf); if(ret==-1) { #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d fstat failed: %s", handle, - file_private_handle->fd, strerror(errno)); + file_private_handle->fd_mapped.fd, strerror(errno)); #endif + SetLastError (ERROR_INVALID_PARAMETER); return(FALSE); } if(last_access!=NULL) { access_ticks=((guint64)last_access->dwHighDateTime << 32) + last_access->dwLowDateTime; + /* This is (time_t)0. We can actually go to INT_MIN, + * but this will do for now. + */ + if (access_ticks < 116444736000000000ULL) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION + ": attempt to set access time too early"); +#endif + SetLastError (ERROR_INVALID_PARAMETER); + return(FALSE); + } + utbuf.actime=(access_ticks - 116444736000000000ULL) / 10000000; } else { utbuf.actime=statbuf.st_atime; @@ -1033,6 +1125,18 @@ static gboolean file_setfiletime(gpointer handle, if(last_write!=NULL) { write_ticks=((guint64)last_write->dwHighDateTime << 32) + last_write->dwLowDateTime; + /* This is (time_t)0. We can actually go to INT_MIN, + * but this will do for now. + */ + if (write_ticks < 116444736000000000ULL) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION + ": attempt to set write time too early"); +#endif + SetLastError (ERROR_INVALID_PARAMETER); + return(FALSE); + } + utbuf.modtime=(write_ticks - 116444736000000000ULL) / 10000000; } else { utbuf.modtime=statbuf.st_mtime; @@ -1051,10 +1155,12 @@ static gboolean file_setfiletime(gpointer handle, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": handle %p [%s] fd %d utime failed: %s", handle, - name, file_private_handle->fd, strerror(errno)); + name, file_private_handle->fd_mapped.fd, + strerror(errno)); #endif g_free (name); + SetLastError (ERROR_INVALID_PARAMETER); return(FALSE); } @@ -1073,6 +1179,7 @@ static void console_close_shared (gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up console handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return; } @@ -1100,16 +1207,22 @@ static void console_close_private (gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up console handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return; } + if (console_private_handle->fd_mapped.assigned == TRUE) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION - ": closing console handle %p with fd %d", handle, - console_private_handle->fd); + g_message(G_GNUC_PRETTY_FUNCTION + ": closing console handle %p with fd %d", handle, + console_private_handle->fd_mapped.fd); #endif - close(console_private_handle->fd); + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (console_private_handle->fd_mapped.fd, NULL); + + close(console_private_handle->fd_mapped.fd); + } } static WapiFileType console_getfiletype(void) @@ -1132,6 +1245,12 @@ static gboolean console_read(gpointer handle, gpointer buffer, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up console handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (console_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -1142,14 +1261,16 @@ static gboolean console_read(gpointer handle, gpointer buffer, if(!(console_handle->fileaccess&GENERIC_READ) && !(console_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, console_private_handle->fd, console_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, console_private_handle->fd_mapped.fd, console_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } do { - ret=read(console_private_handle->fd, buffer, numbytes); + ret=read(console_private_handle->fd_mapped.fd, buffer, + numbytes); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -1157,9 +1278,11 @@ static gboolean console_read(gpointer handle, gpointer buffer, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": read of handle %p fd %d error: %s", handle, - console_private_handle->fd, strerror(errno)); + console_private_handle->fd_mapped.fd, + strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } @@ -1185,6 +1308,12 @@ static gboolean console_write(gpointer handle, gconstpointer buffer, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up console handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (console_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -1195,14 +1324,16 @@ static gboolean console_write(gpointer handle, gconstpointer buffer, if(!(console_handle->fileaccess&GENERIC_WRITE) && !(console_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, console_private_handle->fd, console_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, console_private_handle->fd_mapped.fd, console_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } do { - ret=write(console_private_handle->fd, buffer, numbytes); + ret=write(console_private_handle->fd_mapped.fd, buffer, + numbytes); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -1210,9 +1341,11 @@ static gboolean console_write(gpointer handle, gconstpointer buffer, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": write of handle %p fd %d error: %s", handle, - console_private_handle->fd, strerror(errno)); + console_private_handle->fd_mapped.fd, + strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } if(byteswritten!=NULL) { @@ -1232,6 +1365,7 @@ static void pipe_close_shared (gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return; } @@ -1259,16 +1393,22 @@ static void pipe_close_private (gpointer handle) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return; } + if (pipe_private_handle->fd_mapped.assigned == TRUE) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION - ": closing pipe handle %p with fd %d", handle, - pipe_private_handle->fd); + g_message(G_GNUC_PRETTY_FUNCTION + ": closing pipe handle %p with fd %d", handle, + pipe_private_handle->fd_mapped.fd); #endif - close(pipe_private_handle->fd); + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (pipe_private_handle->fd_mapped.fd, NULL); + + close(pipe_private_handle->fd_mapped.fd); + } } static WapiFileType pipe_getfiletype(void) @@ -1291,9 +1431,15 @@ static gboolean pipe_read (gpointer handle, gpointer buffer, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } - + + if (pipe_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + if(bytesread!=NULL) { *bytesread=0; } @@ -1301,20 +1447,21 @@ static gboolean pipe_read (gpointer handle, gpointer buffer, if(!(pipe_handle->fileaccess&GENERIC_READ) && !(pipe_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, pipe_private_handle->fd, pipe_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, pipe_private_handle->fd_mapped.fd, pipe_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": reading up to %d bytes from pipe %p (fd %d)", numbytes, - handle, pipe_private_handle->fd); + handle, pipe_private_handle->fd_mapped.fd); #endif do { - ret=read(pipe_private_handle->fd, buffer, numbytes); + ret=read(pipe_private_handle->fd_mapped.fd, buffer, numbytes); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -1322,9 +1469,10 @@ static gboolean pipe_read (gpointer handle, gpointer buffer, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": read of handle %p fd %d error: %s", handle, - pipe_private_handle->fd, strerror(errno)); + pipe_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } @@ -1354,6 +1502,12 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + if (pipe_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -1364,20 +1518,21 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer, if(!(pipe_handle->fileaccess&GENERIC_WRITE) && !(pipe_handle->fileaccess&GENERIC_ALL)) { #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, pipe_private_handle->fd, pipe_handle->fileaccess); + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, pipe_private_handle->fd_mapped.fd, pipe_handle->fileaccess); #endif + SetLastError (ERROR_ACCESS_DENIED); return(FALSE); } #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": writing up to %d bytes to pipe %p (fd %d)", numbytes, - handle, pipe_private_handle->fd); + handle, pipe_private_handle->fd_mapped.fd); #endif do { - ret=write(pipe_private_handle->fd, buffer, numbytes); + ret=write(pipe_private_handle->fd_mapped.fd, buffer, numbytes); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -1385,9 +1540,10 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": write of handle %p fd %d error: %s", handle, - pipe_private_handle->fd, strerror(errno)); + pipe_private_handle->fd_mapped.fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(FALSE); } if(byteswritten!=NULL) { @@ -1542,6 +1698,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); #endif + SetLastError (ERROR_INVALID_NAME); return(INVALID_HANDLE_VALUE); } @@ -1552,6 +1709,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, ": unicode conversion returned NULL"); #endif + SetLastError (ERROR_INVALID_NAME); return(INVALID_HANDLE_VALUE); } @@ -1586,6 +1744,19 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, return(INVALID_HANDLE_VALUE); } + if (fd >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + SetLastError (ERROR_TOO_MANY_OPEN_FILES); + + close (fd); + g_free (filename); + + return(INVALID_HANDLE_VALUE); + } + ret = fstat (fd, &statbuf); if (ret == -1) { #ifdef DEBUG @@ -1655,6 +1826,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, g_free (filename); close (fd); + SetLastError (ERROR_GEN_FAILURE); return(INVALID_HANDLE_VALUE); } @@ -1669,13 +1841,16 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up file handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); close (fd); goto cleanup; } - cf_ret = handle; - file_private_handle->fd=fd; - file_private_handle->assigned=TRUE; + _wapi_handle_fd_offset_store (fd, handle); + cf_ret = GINT_TO_POINTER (fd); + + file_private_handle->fd_mapped.fd=fd; + file_private_handle->fd_mapped.assigned=TRUE; file_private_handle->async = ((attrs & FILE_FLAG_OVERLAPPED) != 0); file_handle->filename=_wapi_handle_scratch_store (filename, strlen (filename)); @@ -1693,7 +1868,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": returning handle %p with fd %d", handle, - file_private_handle->fd); + file_private_handle->fd_mapped.fd); #endif cleanup: @@ -1725,6 +1900,7 @@ gboolean DeleteFile(const gunichar2 *name) g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); #endif + SetLastError (ERROR_INVALID_NAME); return(FALSE); } @@ -1735,6 +1911,7 @@ gboolean DeleteFile(const gunichar2 *name) ": unicode conversion returned NULL"); #endif + SetLastError (ERROR_INVALID_NAME); return(FALSE); } @@ -1765,6 +1942,15 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name) { gchar *utf8_name, *utf8_dest_name; int result; + + if(name==NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } utf8_name = mono_unicode_to_external (name); if (utf8_name == NULL) { @@ -1772,8 +1958,19 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name) g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL"); #endif + SetLastError (ERROR_INVALID_NAME); return FALSE; } + + if(dest_name==NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + g_free (utf8_name); + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } utf8_dest_name = mono_unicode_to_external (dest_name); if (utf8_dest_name == NULL) { @@ -1782,6 +1979,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name) #endif g_free (utf8_name); + SetLastError (ERROR_INVALID_NAME); return FALSE; } @@ -1792,6 +1990,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name) if (result != 0 && errno == EXDEV) { /* Try a copy to the new location, and delete the source */ if (CopyFile (name, dest_name, TRUE)==FALSE) { + /* CopyFile will set the error */ return(FALSE); } @@ -1837,6 +2036,15 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name, int remain, n; struct stat st; + if(name==NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } + utf8_src = mono_unicode_to_external (name); if (utf8_src == NULL) { #ifdef DEBUG @@ -1847,6 +2055,16 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name, return(FALSE); } + if(dest_name==NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + g_free (utf8_src); + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } + utf8_dest = mono_unicode_to_external (dest_name); if (utf8_dest == NULL) { #ifdef DEBUG @@ -1958,16 +2176,16 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name, } static mono_once_t stdhandle_once=MONO_ONCE_INIT; -static gpointer stdin_handle=NULL; -static gpointer stdout_handle=NULL; -static gpointer stderr_handle=NULL; +static gpointer stdin_handle=INVALID_HANDLE_VALUE; +static gpointer stdout_handle=INVALID_HANDLE_VALUE; +static gpointer stderr_handle=INVALID_HANDLE_VALUE; static gpointer stdhandle_create (int fd, const guchar *name) { struct _WapiHandle_file *file_handle; struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; - gpointer handle, ret = NULL; + gpointer handle, ret = INVALID_HANDLE_VALUE; int flags; int thr_ret; @@ -1991,6 +2209,7 @@ static gpointer stdhandle_create (int fd, const guchar *name) fd, strerror(errno)); #endif + _wapi_set_last_error_from_errno (); return(INVALID_HANDLE_VALUE); } @@ -1998,7 +2217,8 @@ static gpointer stdhandle_create (int fd, const guchar *name) if(handle==_WAPI_HANDLE_INVALID) { g_warning (G_GNUC_PRETTY_FUNCTION ": error creating file handle"); - return(NULL); + SetLastError (ERROR_GEN_FAILURE); + return(INVALID_HANDLE_VALUE); } pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, @@ -2012,12 +2232,16 @@ static gpointer stdhandle_create (int fd, const guchar *name) if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up console handle %p", handle); + SetLastError (ERROR_INVALID_HANDLE); goto cleanup; } - ret = handle; + + /* We know this is fd 0, 1 or 2 */ + _wapi_handle_fd_offset_store (fd, handle); + ret = GINT_TO_POINTER (fd); - file_private_handle->fd=fd; - file_private_handle->assigned=TRUE; + file_private_handle->fd_mapped.fd=fd; + file_private_handle->fd_mapped.assigned=TRUE; file_handle->filename=_wapi_handle_scratch_store (name, strlen (name)); /* some default security attributes might be needed */ file_handle->security_attributes=0; @@ -2027,7 +2251,7 @@ static gpointer stdhandle_create (int fd, const guchar *name) #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": returning handle %p with fd %d", - handle, file_private_handle->fd); + handle, file_private_handle->fd_mapped.fd); #endif cleanup: @@ -2081,11 +2305,17 @@ gpointer GetStdHandle(WapiStdHandle stdhandle) ": unknown standard handle type"); #endif + SetLastError (ERROR_INVALID_PARAMETER); return(INVALID_HANDLE_VALUE); } + if (handle == INVALID_HANDLE_VALUE) { + SetLastError (ERROR_NO_MORE_FILES); + return(INVALID_HANDLE_VALUE); + } + /* Add a reference to this handle */ - _wapi_handle_ref (handle); + _wapi_handle_ref (_wapi_handle_fd_offset_to_handle (handle)); return(handle); } @@ -2117,12 +2347,21 @@ gpointer GetStdHandle(WapiStdHandle stdhandle) * read due to an attempt to read past the end of the file), %FALSE on * error. */ -gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes, +gboolean ReadFile(gpointer fd_handle, gpointer buffer, guint32 numbytes, guint32 *bytesread, WapiOverlapped *overlapped) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].readfile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2155,12 +2394,21 @@ gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes, * * Return value: %TRUE if the write succeeds, %FALSE on error. */ -gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes, +gboolean WriteFile(gpointer fd_handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten, WapiOverlapped *overlapped) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].writefile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2178,11 +2426,20 @@ gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes, * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean FlushFileBuffers(gpointer handle) +gboolean FlushFileBuffers(gpointer fd_handle) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].flushfile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2199,11 +2456,20 @@ gboolean FlushFileBuffers(gpointer handle) * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean SetEndOfFile(gpointer handle) +gboolean SetEndOfFile(gpointer fd_handle) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].setendoffile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2239,13 +2505,22 @@ gboolean SetEndOfFile(gpointer handle) * If @highmovedistance is not %NULL, the high 32 bits of the new file * pointer are stored there. On failure, %INVALID_SET_FILE_POINTER. */ -guint32 SetFilePointer(gpointer handle, gint32 movedistance, +guint32 SetFilePointer(gpointer fd_handle, gint32 movedistance, gint32 *highmovedistance, WapiSeekMethod method) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_SET_FILE_POINTER); + } + + type = _wapi_handle_type (handle); if(io_ops[type].seek==NULL) { - return(FALSE); + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_SET_FILE_POINTER); } return(io_ops[type].seek (handle, movedistance, highmovedistance, @@ -2263,11 +2538,20 @@ guint32 SetFilePointer(gpointer handle, gint32 movedistance, * %FILE_TYPE_CHAR - @handle is a character device, such as a console. * %FILE_TYPE_PIPE - @handle is a named or anonymous pipe. */ -WapiFileType GetFileType(gpointer handle) +WapiFileType GetFileType(gpointer fd_handle) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FILE_TYPE_UNKNOWN); + } + + type = _wapi_handle_type (handle); if(io_ops[type].getfiletype==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FILE_TYPE_UNKNOWN); } @@ -2290,12 +2574,21 @@ WapiFileType GetFileType(gpointer handle) * @highsize is non-%NULL then the high 32 bits of the file size are * stored here. On failure %INVALID_FILE_SIZE is returned. */ -guint32 GetFileSize(gpointer handle, guint32 *highsize) +guint32 GetFileSize(gpointer fd_handle, guint32 *highsize) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_FILE_SIZE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].getfilesize==NULL) { - return(FALSE); + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_FILE_SIZE); } return(io_ops[type].getfilesize (handle, highsize)); @@ -2326,12 +2619,21 @@ guint32 GetFileSize(gpointer handle, guint32 *highsize) * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean GetFileTime(gpointer handle, WapiFileTime *create_time, +gboolean GetFileTime(gpointer fd_handle, WapiFileTime *create_time, WapiFileTime *last_access, WapiFileTime *last_write) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].getfiletime==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2362,13 +2664,22 @@ gboolean GetFileTime(gpointer handle, WapiFileTime *create_time, * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time, +gboolean SetFileTime(gpointer fd_handle, const WapiFileTime *create_time, const WapiFileTime *last_access, const WapiFileTime *last_write) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].setfiletime==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2415,6 +2726,7 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time, g_message(G_GNUC_PRETTY_FUNCTION ": system_time NULL"); #endif + SetLastError (ERROR_INVALID_PARAMETER); return(FALSE); } @@ -2430,6 +2742,7 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time, g_message(G_GNUC_PRETTY_FUNCTION ": file_time too big"); #endif + SetLastError (ERROR_INVALID_PARAMETER); return(FALSE); } @@ -2766,6 +3079,7 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data) g_free (dir_part); g_free (entry_part); g_free (utf8_pattern); + SetLastError (ERROR_GEN_FAILURE); return(INVALID_HANDLE_VALUE); } @@ -2786,6 +3100,7 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data) entry_part = NULL; g_free (utf8_pattern); utf8_pattern = NULL; + SetLastError (ERROR_INVALID_HANDLE); goto cleanup; } @@ -3054,12 +3369,22 @@ gboolean CreateDirectory (const gunichar2 *name, WapiSecurityAttributes *securit struct stat buf; guint32 attrs; + if (name == NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } + utf8_name = mono_unicode_to_external (name); if (utf8_name == NULL) { #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL"); #endif + SetLastError (ERROR_INVALID_NAME); return FALSE; } @@ -3106,6 +3431,15 @@ gboolean RemoveDirectory (const gunichar2 *name) { gchar *utf8_name; int result; + + if (name == NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } utf8_name = mono_unicode_to_external (name); if (utf8_name == NULL) { @@ -3113,6 +3447,7 @@ gboolean RemoveDirectory (const gunichar2 *name) g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL"); #endif + SetLastError (ERROR_INVALID_NAME); return FALSE; } @@ -3140,6 +3475,15 @@ guint32 GetFileAttributes (const gunichar2 *name) struct stat buf; int result; + if (name == NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } + utf8_name = mono_unicode_to_external (name); if (utf8_name == NULL) { #ifdef DEBUG @@ -3186,8 +3530,18 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev g_message (G_GNUC_PRETTY_FUNCTION ": info level %d not supported.", level); #endif + SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } + + if (name == NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } utf8_name = mono_unicode_to_external (name); if (utf8_name == NULL) { @@ -3254,8 +3608,26 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs) * Currently we only handle one *internal* case, with a value that is * not standard: 0x80000000, which means `set executable bit' */ + + if (name == NULL) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return(FALSE); + } utf8_name = mono_unicode_to_external (name); + if (utf8_name == NULL) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL"); +#endif + + SetLastError (ERROR_INVALID_NAME); + return FALSE; + } + result = stat (utf8_name, &buf); if (result != 0) { g_free (utf8_name); @@ -3367,10 +3739,14 @@ extern gboolean SetCurrentDirectory (const gunichar2 *path) return result; } -int _wapi_file_handle_to_fd (gpointer handle) +/* When we're confident there are no more bugs in the fd->handle + * mapping, this can be replaced as a no-op: GPOINTER_TO_INT(fd_handle) == fd + */ +int _wapi_file_handle_to_fd (gpointer fd_handle) { struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": looking up fd for %p", handle); @@ -3389,17 +3765,25 @@ int _wapi_file_handle_to_fd (gpointer handle) g_message (G_GNUC_PRETTY_FUNCTION ": returning -1"); #endif + SetLastError (ERROR_INVALID_HANDLE); return(-1); } } } + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); + return(-1); + } + #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": returning %d", - file_private_handle->fd); + file_private_handle->fd_mapped.fd); #endif - return(file_private_handle->fd); + g_assert (file_private_handle->fd_mapped.fd == GPOINTER_TO_INT (fd_handle)); + + return(file_private_handle->fd_mapped.fd); } gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, @@ -3434,6 +3818,20 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, _wapi_set_last_error_from_errno (); return(FALSE); } + + if (filedes[0] >= _wapi_fd_offset_table_size || + filedes[1] >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + SetLastError (ERROR_TOO_MANY_OPEN_FILES); + + close (filedes[0]); + close (filedes[1]); + + return(FALSE); + } /* filedes[0] is open for reading, filedes[1] for writing */ @@ -3443,6 +3841,8 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, ": error creating pipe read handle"); close (filedes[0]); close (filedes[1]); + SetLastError (ERROR_GEN_FAILURE); + return(FALSE); } @@ -3458,6 +3858,7 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle); close (filedes[0]); close (filedes[1]); + SetLastError (ERROR_INVALID_HANDLE); goto cleanup; } @@ -3469,6 +3870,8 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, close (filedes[0]); close (filedes[1]); + SetLastError (ERROR_GEN_FAILURE); + goto cleanup; } @@ -3487,26 +3890,27 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, close (filedes[0]); close (filedes[1]); + SetLastError (ERROR_INVALID_HANDLE); goto write_cleanup; } cp_ret = TRUE; - pipe_read_private_handle->fd=filedes[0]; - pipe_read_private_handle->assigned=TRUE; + pipe_read_private_handle->fd_mapped.fd=filedes[0]; + pipe_read_private_handle->fd_mapped.assigned=TRUE; pipe_read_handle->fileaccess=GENERIC_READ; - *readpipe=read_handle; + _wapi_handle_fd_offset_store (filedes[0], read_handle); + *readpipe=GINT_TO_POINTER (filedes[0]); - pipe_write_private_handle->fd=filedes[1]; - pipe_write_private_handle->assigned=TRUE; + pipe_write_private_handle->fd_mapped.fd=filedes[1]; + pipe_write_private_handle->fd_mapped.assigned=TRUE; pipe_write_handle->fileaccess=GENERIC_WRITE; - *writepipe=write_handle; + _wapi_handle_fd_offset_store (filedes[1], write_handle); + *writepipe=GINT_TO_POINTER (filedes[1]); #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION - ": Returning pipe: read handle %p, write handle %p", - read_handle, write_handle); + g_message (G_GNUC_PRETTY_FUNCTION ": Returning pipe: read handle %p (fd %d), write handle %p (fd %d)", read_handle, filedes[0], write_handle, filedes[1]); #endif write_cleanup: @@ -3579,7 +3983,7 @@ guint32 GetTempPath (guint32 len, gunichar2 *buf) } gboolean -_wapi_io_add_callback (gpointer handle, +_wapi_io_add_callback (gpointer fd_handle, WapiOverlappedCB callback, guint64 flags G_GNUC_UNUSED) { @@ -3588,6 +3992,12 @@ _wapi_io_add_callback (gpointer handle, gboolean ok; int thr_ret; gboolean ret = FALSE; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, (gpointer *) &file_handle, @@ -3761,13 +4171,19 @@ static gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length) return(TRUE); } -gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, +gboolean LockFile (gpointer fd_handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high) { struct _WapiHandle_file *file_handle; struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; off_t offset, length; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, (gpointer *)&file_handle, @@ -3779,11 +4195,16 @@ gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, return(FALSE); } + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) { #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif SetLastError (ERROR_ACCESS_DENIED); return(FALSE); @@ -3796,7 +4217,7 @@ gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": Locking handle %p fd %d, offset %lld, length %lld", - handle, file_private_handle->fd, offset, length); + handle, file_private_handle->fd_mapped.fd, offset, length); #endif #else offset = offset_low; @@ -3805,21 +4226,28 @@ gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": Locking handle %p fd %d, offset %ld, length %ld", - handle, file_private_handle->fd, offset, length); + handle, file_private_handle->fd_mapped.fd, offset, length); #endif #endif - return(_wapi_lock_file_region (file_private_handle->fd, offset, - length)); + return(_wapi_lock_file_region (file_private_handle->fd_mapped.fd, + offset, length)); } -gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, - guint32 length_low, guint32 length_high) +gboolean UnlockFile (gpointer fd_handle, guint32 offset_low, + guint32 offset_high, guint32 length_low, + guint32 length_high) { struct _WapiHandle_file *file_handle; struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; off_t offset, length; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, (gpointer *)&file_handle, @@ -3831,11 +4259,16 @@ gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, return(FALSE); } + if (file_private_handle->fd_mapped.assigned == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) { #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess); + g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess); #endif SetLastError (ERROR_ACCESS_DENIED); return(FALSE); @@ -3848,7 +4281,7 @@ gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": Unlocking handle %p fd %d, offset %lld, length %lld", - handle, file_private_handle->fd, offset, length); + handle, file_private_handle->fd_mapped.fd, offset, length); #endif #else offset = offset_low; @@ -3857,10 +4290,10 @@ gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": Unlocking handle %p fd %d, offset %ld, length %ld", - handle, file_private_handle->fd, offset, length); + handle, file_private_handle->fd_mapped.fd, offset, length); #endif #endif - return(_wapi_unlock_file_region (file_private_handle->fd, offset, - length)); + return(_wapi_unlock_file_region (file_private_handle->fd_mapped.fd, + offset, length)); } diff --git a/mono/io-layer/mutexes.c b/mono/io-layer/mutexes.c index ee736aac2c2..ee10921578a 100644 --- a/mono/io-layer/mutexes.c +++ b/mono/io-layer/mutexes.c @@ -23,9 +23,8 @@ #undef DEBUG /* This is used to serialise mutex creation when names are given - * (FIXME: make it process-shared) */ -static mono_mutex_t named_mutex_mutex = MONO_MUTEX_INITIALIZER; +static mono_mutex_t named_mutex_mutex; static void mutex_close_shared (gpointer handle); static void mutex_signal(gpointer handle); @@ -44,6 +43,23 @@ static mono_once_t mutex_ops_once=MONO_ONCE_INIT; static void mutex_ops_init (void) { + int thr_ret; +#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1 + pthread_mutexattr_t mutex_shared_attr; + + thr_ret = mono_mutexattr_init (&mutex_shared_attr); + g_assert (thr_ret == 0); + + thr_ret = mono_mutexattr_setpshared (&mutex_shared_attr, + PTHREAD_PROCESS_SHARED); + g_assert (thr_ret == 0); + + thr_ret = mono_mutex_init (&named_mutex_mutex, &mutex_shared_attr); + g_assert (thr_ret == 0); +#else + thr_ret = mono_mutex_init (&named_mutex_mutex, NULL); +#endif + _wapi_handle_register_capabilities (WAPI_HANDLE_MUTEX, WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL | diff --git a/mono/io-layer/socket-private.h b/mono/io-layer/socket-private.h index 47f14c1315f..4da7f58d8ad 100644 --- a/mono/io-layer/socket-private.h +++ b/mono/io-layer/socket-private.h @@ -22,7 +22,7 @@ struct _WapiHandle_socket struct _WapiHandlePrivate_socket { - int fd; + WapiFDMapped fd_mapped; }; #endif /* _WAPI_SOCKET_PRIVATE_H_ */ diff --git a/mono/io-layer/sockets.c b/mono/io-layer/sockets.c index 3f48f02af8e..df7ac8a25dc 100644 --- a/mono/io-layer/sockets.c +++ b/mono/io-layer/sockets.c @@ -97,21 +97,28 @@ static void socket_close_private (gpointer handle) g_ptr_array_remove_fast(sockets, GUINT_TO_POINTER (handle)); - do { - ret=close(socket_private_handle->fd); - } - while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); + if (socket_private_handle->fd_mapped.assigned == TRUE) { + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (socket_private_handle->fd_mapped.fd, NULL); + + do { + ret=close(socket_private_handle->fd_mapped.fd); + } + while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); - if(ret==-1) { - gint errnum = errno; + if(ret==-1) { + gint errnum = errno; #ifdef DEBUG - g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s", - strerror(errno)); + g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s", + strerror(errno)); #endif - errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION); - WSASetLastError (errnum); + errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION); + WSASetLastError (errnum); - return; + return; + } + } else { + WSASetLastError(WSAENOTSOCK); } } @@ -205,20 +212,27 @@ int WSAGetLastError(void) return(err); } -int closesocket(guint32 handle) +int closesocket(guint32 fd_handle) { - _wapi_handle_unref (GUINT_TO_POINTER (handle)); + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd_handle)); + + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + WSASetLastError (WSAENOTSOCK); + return(0); + } + + _wapi_handle_unref (handle); return(0); } -guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, - socklen_t *addrlen) +guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; struct _WapiHandlePrivate_socket *new_socket_private_handle; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); gpointer new_handle; gboolean ok; - int fd; + int new_fd; int thr_ret; guint32 ret = INVALID_SOCKET; @@ -227,21 +241,18 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, return(INVALID_SOCKET); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(INVALID_SOCKET); } do { - fd=accept(socket_private_handle->fd, addr, addrlen); + new_fd=accept(fd, addr, addrlen); } - while (fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); + while (new_fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); - if(fd==-1) { + if(new_fd==-1) { gint errnum = errno; #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s", @@ -254,10 +265,23 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, return(INVALID_SOCKET); } + if (new_fd >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + WSASetLastError (WSASYSCALLFAILURE); + + close (new_fd); + + return(INVALID_SOCKET); + } + new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET); if(new_handle==_WAPI_HANDLE_INVALID) { g_warning (G_GNUC_PRETTY_FUNCTION ": error creating socket handle"); + WSASetLastError (ERROR_GEN_FAILURE); return(INVALID_SOCKET); } @@ -270,17 +294,21 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, (gpointer *)&new_socket_private_handle); if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + ": error looking up new socket handle %p", + new_handle); goto cleanup; } - ret = GPOINTER_TO_UINT (new_handle); + + _wapi_handle_fd_offset_store (new_fd, new_handle); + ret = new_fd; - new_socket_private_handle->fd=fd; + new_socket_private_handle->fd_mapped.fd = new_fd; + new_socket_private_handle->fd_mapped.assigned = TRUE; #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": returning newly accepted socket handle %p with fd %d", - new_handle, new_socket_private_handle->fd); + new_handle, new_socket_private_handle->fd_mapped.fd); #endif cleanup: @@ -291,27 +319,23 @@ cleanup: return(ret); } -int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen) +int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { WSASetLastError(WSANOTINITIALISED); return(SOCKET_ERROR); } - - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=bind(socket_private_handle->fd, my_addr, addrlen); + ret=bind(fd, my_addr, addrlen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -326,11 +350,10 @@ int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen) return(ret); } -int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, +int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, socklen_t addrlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; gint errnum; @@ -339,17 +362,14 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } do { - ret=connect(socket_private_handle->fd, serv_addr, addrlen); + ret=connect(fd, serv_addr, addrlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -361,11 +381,11 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, errnum = errno; - ret=setsockopt (socket_private_handle->fd, SOL_SOCKET, - SO_BROADCAST, &true, sizeof(true)); + ret=setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true, + sizeof(true)); if(ret==0) { do { - ret=connect (socket_private_handle->fd, serv_addr, addrlen); + ret=connect (fd, serv_addr, addrlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); } @@ -386,11 +406,9 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, return(ret); } -int _wapi_getpeername(guint32 handle, struct sockaddr *name, - socklen_t *namelen) +int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -398,16 +416,13 @@ int _wapi_getpeername(guint32 handle, struct sockaddr *name, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=getpeername(socket_private_handle->fd, name, namelen); + ret=getpeername(fd, name, namelen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -424,11 +439,9 @@ int _wapi_getpeername(guint32 handle, struct sockaddr *name, return(ret); } -int _wapi_getsockname(guint32 handle, struct sockaddr *name, - socklen_t *namelen) +int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -436,16 +449,13 @@ int _wapi_getsockname(guint32 handle, struct sockaddr *name, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=getsockname(socket_private_handle->fd, name, namelen); + ret=getsockname(fd, name, namelen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -462,11 +472,10 @@ int _wapi_getsockname(guint32 handle, struct sockaddr *name, return(ret); } -int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval, +int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval, socklen_t *optlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -474,17 +483,13 @@ int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=getsockopt(socket_private_handle->fd, level, optname, optval, - optlen); + ret=getsockopt(fd, level, optname, optval, optlen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -501,10 +506,9 @@ int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval, return(ret); } -int _wapi_listen(guint32 handle, int backlog) +int _wapi_listen(guint32 fd, int backlog) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -512,16 +516,13 @@ int _wapi_listen(guint32 handle, int backlog) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=listen(socket_private_handle->fd, backlog); + ret=listen(fd, backlog); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -538,19 +539,18 @@ int _wapi_listen(guint32 handle, int backlog) return(0); } -int _wapi_recv(guint32 handle, void *buf, size_t len, int recv_flags) +int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags) { - return(_wapi_recvfrom(handle, buf, len, recv_flags, NULL, 0)); + return(_wapi_recvfrom(fd, buf, len, recv_flags, NULL, 0)); } -int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags, +int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags, struct sockaddr *from, socklen_t *fromlen) { #ifndef HAVE_MSG_NOSIGNAL void (*old_sigpipe)(int); // old SIGPIPE handler #endif - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -558,26 +558,22 @@ int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } #ifdef HAVE_MSG_NOSIGNAL do { - ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags | MSG_NOSIGNAL, from, + ret=recvfrom(fd, buf, len, recv_flags | MSG_NOSIGNAL, from, fromlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); #else old_sigpipe = signal(SIGPIPE, SIG_IGN); do { - ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags, from, - fromlen); + ret=recvfrom(fd, buf, len, recv_flags, from, fromlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); signal(SIGPIPE, old_sigpipe); @@ -598,13 +594,12 @@ int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags, return(ret); } -int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags) +int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags) { #ifndef HAVE_MSG_NOSIGNAL void (*old_sigpipe)(int); // old SIGPIPE handler #endif - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -612,24 +607,21 @@ int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } #ifdef HAVE_MSG_NOSIGNAL do { - ret=send(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL); + ret=send(fd, msg, len, send_flags | MSG_NOSIGNAL); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); #else old_sigpipe = signal(SIGPIPE, SIG_IGN); do { - ret=send(socket_private_handle->fd, msg, len, send_flags); + ret=send(fd, msg, len, send_flags); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); signal(SIGPIPE, old_sigpipe); @@ -649,14 +641,13 @@ int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags) return(ret); } -int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags, +int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags, const struct sockaddr *to, socklen_t tolen) { #ifndef HAVE_MSG_NOSIGNAL void (*old_sigpipe)(int); // old SIGPIPE handler #endif - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -664,24 +655,21 @@ int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } #ifdef HAVE_MSG_NOSIGNAL do { - ret=sendto(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen); + ret=sendto(fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); #else old_sigpipe = signal(SIGPIPE, SIG_IGN); do { - ret=sendto(socket_private_handle->fd, msg, len, send_flags, to, tolen); + ret=sendto(fd, msg, len, send_flags, to, tolen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); signal(SIGPIPE, old_sigpipe); @@ -701,11 +689,10 @@ int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags, return(ret); } -int _wapi_setsockopt(guint32 handle, int level, int optname, +int _wapi_setsockopt(guint32 fd, int level, int optname, const void *optval, socklen_t optlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -713,17 +700,13 @@ int _wapi_setsockopt(guint32 handle, int level, int optname, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=setsockopt(socket_private_handle->fd, level, optname, optval, - optlen); + ret=setsockopt(fd, level, optname, optval, optlen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -740,10 +723,9 @@ int _wapi_setsockopt(guint32 handle, int level, int optname, return(ret); } -int _wapi_shutdown(guint32 handle, int how) +int _wapi_shutdown(guint32 fd, int how) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -751,16 +733,13 @@ int _wapi_shutdown(guint32 handle, int how) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=shutdown(socket_private_handle->fd, how); + ret=shutdown(fd, how); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -802,6 +781,18 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 u return(INVALID_SOCKET); } + + if (fd >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + WSASetLastError (WSASYSCALLFAILURE); + close (fd); + + return(INVALID_SOCKET); + } + mono_once (&socket_ops_once, socket_ops_init); @@ -824,14 +815,17 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 u ": error looking up socket handle %p", handle); goto cleanup; } - ret = GPOINTER_TO_UINT (handle); + + _wapi_handle_fd_offset_store (fd, handle); + ret = fd; - socket_private_handle->fd=fd; + socket_private_handle->fd_mapped.fd = fd; + socket_private_handle->fd_mapped.assigned = TRUE; #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": returning socket handle %p with fd %d", handle, - socket_private_handle->fd); + socket_private_handle->fd_mapped.fd); #endif cleanup: @@ -884,13 +878,12 @@ struct hostent *_wapi_gethostbyname(const char *hostname) } int -WSAIoctl (guint32 handle, gint32 command, - gchar *input, gint i_len, - gchar *output, gint o_len, glong *written, - void *unused1, void *unused2) +WSAIoctl (guint32 fd, gint32 command, + gchar *input, gint i_len, + gchar *output, gint o_len, glong *written, + void *unused1, void *unused2) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; gchar *buffer = NULL; @@ -899,12 +892,8 @@ WSAIoctl (guint32 handle, gint32 command, return(SOCKET_ERROR); } - ok = _wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - - if (ok == FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return SOCKET_ERROR; } @@ -912,7 +901,7 @@ WSAIoctl (guint32 handle, gint32 command, if (i_len > 0) buffer = g_memdup (input, i_len); - ret = ioctl (socket_private_handle->fd, command, buffer); + ret = ioctl (fd, command, buffer); if (ret == -1) { gint errnum = errno; #ifdef DEBUG @@ -941,10 +930,9 @@ WSAIoctl (guint32 handle, gint32 command, return 0; } -int ioctlsocket(guint32 handle, gint32 command, gpointer arg) +int ioctlsocket(guint32 fd, gint32 command, gpointer arg) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -952,11 +940,8 @@ int ioctlsocket(guint32 handle, gint32 command, gpointer arg) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } @@ -976,19 +961,19 @@ int ioctlsocket(guint32 handle, gint32 command, gpointer arg) * connect to return EINPROGRESS, but the ioctl doesn't seem to) */ if(command==FIONBIO) { - ret=fcntl(socket_private_handle->fd, F_GETFL, 0); + ret=fcntl(fd, F_GETFL, 0); if(ret!=-1) { if(*(gboolean *)arg) { ret &= ~O_NONBLOCK; } else { ret |= O_NONBLOCK; } - ret=fcntl(socket_private_handle->fd, F_SETFL, ret); + ret=fcntl(fd, F_SETFL, ret); } } else #endif /* O_NONBLOCK */ { - ret=ioctl(socket_private_handle->fd, command, arg); + ret=ioctl(fd, command, arg); } if(ret==-1) { gint errnum = errno; @@ -1036,55 +1021,43 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds, return(ret); } -void _wapi_FD_CLR(guint32 handle, fd_set *set) +void _wapi_FD_CLR(guint32 fd, fd_set *set) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return; } - FD_CLR(socket_private_handle->fd, set); + FD_CLR(fd, set); } -int _wapi_FD_ISSET(guint32 handle, fd_set *set) +int _wapi_FD_ISSET(guint32 fd, fd_set *set) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(0); } - return(FD_ISSET(socket_private_handle->fd, set)); + return(FD_ISSET(fd, set)); } -void _wapi_FD_SET(guint32 handle, fd_set *set) +void _wapi_FD_SET(guint32 fd, fd_set *set) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return; } - FD_SET(socket_private_handle->fd, set); + FD_SET(fd, set); } #ifdef USE_AIO @@ -1119,29 +1092,23 @@ async_notifier (union sigval sig) } static gboolean -do_aio_call (gboolean is_read, gpointer handle, gpointer buffer, +do_aio_call (gboolean is_read, gpointer fd_handle, gpointer buffer, guint32 numbytes, guint32 *out_bytes, gpointer ares, SocketAsyncCB callback) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; - int fd; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + int fd = GPOINTER_TO_UINT (fd_handle); struct aiocb *aio; int result; notifier_data_t *ndata; - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if (ok == FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", (guint) handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return FALSE; } - fd = socket_private_handle->fd; - ndata = g_new0 (notifier_data_t, 1); aio = g_new0 (struct aiocb, 1); ndata->ares = ares; diff --git a/mono/io-layer/threads.c b/mono/io-layer/threads.c index b9ddc6aa3dc..31c1176a12c 100644 --- a/mono/io-layer/threads.c +++ b/mono/io-layer/threads.c @@ -99,9 +99,7 @@ static void thread_close_private (gpointer handle) thread_handle->thread->id); #endif - if(thread_handle->thread!=NULL) { - _wapi_timed_thread_destroy (thread_handle->thread); - } + thread_handle->thread=NULL; } static void thread_own (gpointer handle) @@ -628,6 +626,10 @@ guint32 ResumeThread(gpointer handle) return(0xFFFFFFFF); } + if (thread_private_handle->thread == NULL) { + return(0xFFFFFFFF); + } + #ifdef WITH_INCLUDED_LIBGC if (thread_private_handle->thread->suspend_count <= 1) _wapi_timed_thread_resume (thread_private_handle->thread); @@ -670,6 +672,10 @@ guint32 SuspendThread(gpointer handle) return(0xFFFFFFFF); } + if (thread_private_handle->thread == NULL) { + return(0xFFFFFFFF); + } + if (!thread_private_handle->thread->suspend_count) { if (handle == current) _wapi_timed_thread_suspend (thread_private_handle->thread); diff --git a/mono/io-layer/timed-thread.c b/mono/io-layer/timed-thread.c index c0d737862a2..6599e0660f3 100644 --- a/mono/io-layer/timed-thread.c +++ b/mono/io-layer/timed-thread.c @@ -254,6 +254,8 @@ int _wapi_timed_thread_join(TimedThread *thread, struct timespec *timeout, if(exitstatus!=NULL) { *exitstatus = thread->exitstatus; } + + _wapi_timed_thread_destroy (thread); } return(result); } diff --git a/mono/io-layer/wait.c b/mono/io-layer/wait.c index e3d07b3a255..a236d17ed3e 100644 --- a/mono/io-layer/wait.c +++ b/mono/io-layer/wait.c @@ -354,9 +354,15 @@ static gboolean test_and_own (guint32 numobjects, gpointer *handles, done = _wapi_handle_count_signalled_handles (numobjects, handles, waitall, count, lowest); if (done == TRUE) { - for (i = 0; i < numobjects; i++) { - if (_wapi_handle_issignalled (handles[i])) { - _wapi_handle_ops_own (handles[i]); + if (waitall == TRUE) { + for (i = 0; i < numobjects; i++) { + if (_wapi_handle_issignalled (handles[i])) { + _wapi_handle_ops_own (handles[i]); + } + } + } else { + if (_wapi_handle_issignalled (handles[*lowest])) { + _wapi_handle_ops_own (handles[*lowest]); } } } diff --git a/mono/io-layer/wapi-private.h b/mono/io-layer/wapi-private.h index 59ec8defe30..2a7203c6937 100644 --- a/mono/io-layer/wapi-private.h +++ b/mono/io-layer/wapi-private.h @@ -35,7 +35,7 @@ /* Increment this whenever an incompatible change is made to the * shared handle structure. */ -#define _WAPI_HANDLE_VERSION 1 +#define _WAPI_HANDLE_VERSION 3 typedef enum { WAPI_HANDLE_UNUSED=0, @@ -59,6 +59,19 @@ typedef struct guint32 name; } WapiSharedNamespace; +/* The boolean is for distinguishing between a zeroed struct being not + * as yet assigned, and one containing a valid fd 0. It's also used + * to signal that a previously-good fd has been reused behind our + * back, so we need to invalidate the handle that thought it owned the + * fd. + */ +typedef struct +{ + int fd; + gboolean assigned; +} WapiFDMapped; + + typedef enum { WAPI_HANDLE_CAP_WAIT=0x01, WAPI_HANDLE_CAP_SIGNAL=0x02, @@ -152,6 +165,7 @@ struct _WapiHandleShared_list { guchar daemon[MONO_SIZEOF_SUNPATH]; _wapi_daemon_status daemon_running; + guint32 fd_offset_table_size; #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1 mono_mutex_t signal_mutex; diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 662605f6c5c..d23a628905c 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,212 @@ +2004-10-07 Jackson Harper <jackson@ximian.com> + + * culture-info-tables.h: regenerate file. + +2004-10-07 Zoltan Varga <vargaz@freemail.hu> + + * loader.c (mono_lookup_pinvoke_call): Try the dllname prefixed with + 'lib' too. Fixes #63130. + +2004-10-02 Ben Maurer <bmaurer@ximian.com> + + * threadpool.c: the ares hashtable needs a critical section around it. + this prevents some nasty segfaults + +2004-09-30 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * threads.c: don't call mono_thread_detach() in start_wrapper(), + avoiding a possible hang in GetCurrentThreadId(0). Fixes bug #65379. + +2004-09-28 Zoltan Varga <vargaz@freemail.hu> + + * reflection.c (method_encode_code): Align method headers properly. + Fixes #66025. + +2004-09-25 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * threadpool.c: reuse allocated slots in the queue. + +2004-09-23 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * appdomain.c: + (mono_domain_set): allow setting a domain that is being unloaded. + (mono_domain_unload): invoke the DomainUnload callbacks in the domain + being unloaded. + +2004-09-18 Martin Baulig <martin@ximian.com> + + * mono-debug.c, debug-mono-symfile.c: Merged my locking changes + from HEAD. + +2004-09-17 Zoltan Varga <vargaz@freemail.hu> + + * loader.c (mono_lookup_pinvoke_call): Add support for stdcall name + mangling. + +2004-09-16 Lluis Sanchez Gual <lluis@novell.com> + + * locales.c: nullify the ICU_collator member of CompareInfo when it is + finalized. There where random SIGSEVs at program termination, when + an object being finalized was trying to do a string comparison and + the current culture was already finalized. + +2004-09-16 Zoltan Varga <vargaz@freemail.hu> + + * appdomain.c (ves_icall_System_AppDomain_createDomain): Load all + assemblies from the parent. Fixes #65665. + +2004-09-14 Lluis Sanchez Gual <lluis@novell.com> + + * object.c: Added a "done" flag to TypeInitializationLock. This avoids + false deadlock checks in class initialization. + +2004-09-09 Zoltan Varga <vargaz@freemail.hu> + + * reflection.h reflection.c loader.c: Allow dynamic construction of + pinvoke methods. Fixes #65571. + +2004-09-08 Lluis Sanchez Gual <lluis@novell.com> + + * object.c: In mono_message_invoke, fill the output parameter array after + calling the managed method (it was done before the call). This fixes + bug #59299. + +2004-09-08 Zoltan Varga <vargaz@freemail.hu> + + * image.c (mono_image_close): Applied patch from + vasantha.paulraj@honeywell.com (Vasantha selvi). Fix crash when an + assembly is loaded multiple times from data. + + * image.c (mono_image_open): Fix warning. + +2004-09-07 Zoltan Varga <vargaz@freemail.hu> + + * reflection.c (mono_reflection_create_runtime_class): Initialize + klass->nested_classes. Fixes #61224. + +2004-09-06 Zoltan Varga <vargaz@freemail.hu> + + * reflection.c (mono_param_get_objects): Initialize the default value + with DBNull.Value, not null. Fixes #62123. + +2004-09-01 Miguel de Icaza <miguel@ximian.com> + + * marshal.c (mono_marshal_get_managed_wrapper): Remove FIXME and + throw an exception with a cute explanation. + +2004-09-06 Dick Porter <dick@ximian.com> + + * process.c (ves_icall_System_Diagnostics_Process_Start_internal): + Close the new process's thread handle, as we don't use it. The + handle stays around forever otherwise. + +2004-09-05 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * assembly.c: provide more information when loading an assembly fails. + +2004-09-04 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * filewatcher.c: don't expect the development fam package to be + installed. If HAVE_KQUEUE return mode 3 to use the new kqueue + watcher. Patch by Geoff Norton. + +2004-09-02 Zoltan Varga <vargaz@freemail.hu> + + * marshal.c (mono_marshal_alloc): Return a valid pointer on size 0 + as well. + +2004-08-28 Ben Maurer <bmaurer@users.sourceforge.net> + + * gc.c: actually enable paolo's patch to make GC warnings + use the trace api. + +2004-08-23 Zoltan Varga <vargaz@freemail.hu> + + * metadata.c (mono_metadata_parse_type): Alloc pinned, byref and + custom modifiers to be in any order. Fixes #61990. + +Thu Aug 5 17:11:44 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * reflection.c: fix to deal with object[] arrays in custom ctors + (bug #62550). + +Tue Aug 3 17:54:17 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * gc.c: make GC warning messages use the trace API, they are just + noise to most of the users. + +Tue Aug 3 16:40:17 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * gc.c, object.h: mono_gc_handle_*() interface and + AddrOfPinnedObject fixes. GC handle support even without GC. + +Fri Jul 30 16:49:05 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * object.c: always create an object if null is passed + to Invoke() where a valuetype is expected. + +2004-07-29 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * appdomain.c: hack to build correctly the private bin path on windows. + Fixes bug #61991. + +2004-07-28 Dick Porter <dick@ximian.com> + + * socket-io.c + (ves_icall_System_Net_Sockets_Socket_RecvFrom_internal): Check + returned sockaddr size before creating the remote address object. + Patch by Nick Vaughan (dev@6wardlaw.freeserve.co.uk), fixes bug + 61608. + +2004-07-28 Dick Porter <dick@ximian.com> + + * locales.c (string_invariant_compare_char): Fix invariant char + compares between upper and lower cases. Fixes bug 61458. + +Tue Jul 27 15:58:19 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * debug-mono-symfile.c: fix one more endianess issue, from a patch + by Geoff Norton (<gnorton@customerdna.com>). + +Tue Jul 27 15:47:17 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * class.c: fix class loads for pointer types (typeof(int) != + typeof(int*)). + +2004-07-24 Martin Baulig <martin@ximian.com> + + * reflection.c (mono_image_get_type_info): Only write a class + layout entry if we actually have a size or a packing size. + +2004-07-13 Peter Williams <peter@newton.cx> + + * process.c (complete_path): Make sure we don't attempt to execute + directories. + +2004-07-11 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * debug-helpers.c: undo my previous patch and fixed the real issue in + ../mini/exceptions-x86.c + +2004-07-11 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * debug-helpers.c: prevent SIGSEGV. It happened running xsp on monodoc + when no HOME env. variable was set and a NullRef was thrown in a .cctor + called from other .cctors. + +2004-07-09 Dick Porter <dick@ximian.com> + + * locales.c (ves_icall_System_String_InternalReplace_Str_Comp): + Don't do any more processing if the matched length was 0. It was + increasing the size of the string before. Fixes bug 61167. + +2004-07-09 Dick Porter <dick@ximian.com> + + * socket-io.h: + * socket-io.c + (ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal): + Add support for SO_PEERCRED if its available. + 2004-07-03 Zoltan Varga <vargaz@freemail.hu> * marshal.c: Fix managed->native stringbuilder marshalling. Implement @@ -10918,4 +11127,3 @@ Tue Jul 3 18:33:32 CEST 2001 Paolo Molaro <lupus@ximian.com> Beta2. * mono/metadata/assembly.c (load_metadata_ptrs): Fix for Beta2 - diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index a917a9ecd19..c87e2b01bf2 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -44,6 +44,9 @@ mono_domain_assembly_preload (MonoAssemblyName *aname, static void mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data); +static void +add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass); + static MonoMethod * look_for_method_by_name (MonoClass *klass, const gchar *name); @@ -249,12 +252,12 @@ mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb) * if it is being unloaded. * Returns: * - TRUE on success - * - FALSE if the domain is being unloaded + * - FALSE if the domain is unloaded */ gboolean mono_domain_set (MonoDomain *domain, gboolean force) { - if (!force && (domain->state == MONO_APPDOMAIN_UNLOADING || domain->state == MONO_APPDOMAIN_UNLOADED)) + if (!force && domain->state == MONO_APPDOMAIN_UNLOADED) return FALSE; mono_domain_set_internal (domain); @@ -357,10 +360,16 @@ ves_icall_System_AppDomain_getCurDomain () return add->domain; } +static void +add_assembly_to_domain (gpointer key, gpointer value, gpointer user_data) +{ + add_assemblies_to_domain ((MonoDomain*)user_data, (MonoAssembly*)value); +} + MonoAppDomain * ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup) { - /*MonoDomain *domain = mono_domain_get (); */ + MonoDomain *domain = mono_domain_get (); MonoClass *adclass; MonoAppDomain *ad; MonoDomain *data; @@ -381,7 +390,10 @@ ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomai mono_context_init (data); - /* FIXME: what to do next ? */ + /* The new appdomain should have all assemblies loaded */ + mono_domain_lock (domain); + g_hash_table_foreach (domain->assemblies, add_assembly_to_domain, data); + mono_domain_unlock (domain); return ad; } @@ -547,9 +559,17 @@ reduce_path (const gchar *dirname) for (tmp = list; tmp; tmp = tmp->next) { gchar *data = (gchar *) tmp->data; - if (data && *data) - g_string_append_printf (result, "%c%s", G_DIR_SEPARATOR, - (char *) tmp->data); + if (data && *data) { +#ifdef PLATFORM_WIN32 + if (result->len == 0) + g_string_append_printf (result, "%s\\", data); + else if (result->str [result->len - 1] == '\\') + g_string_append_printf (result, "%s", data); + else +#endif + g_string_append_printf (result, "%c%s", + G_DIR_SEPARATOR, data); + } } res = result->str; @@ -1000,10 +1020,8 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file, assembly = mono_assembly_open (filename, NULL); g_free (filename); - if (!assembly) { - mono_raise_exception ((MonoException *)mono_exception_from_name ( - mono_defaults.corlib, "System.IO", "FileNotFoundException")); - } + if (!assembly) + mono_raise_exception (mono_get_exception_file_not_found (filename)); image = assembly->image; @@ -1112,7 +1130,7 @@ ves_icall_System_AppDomain_InternalSetContext (MonoAppContext *mc) MONO_ARCH_SAVE_REGS; mono_context_set (mc); - + return old_context; } @@ -1215,6 +1233,7 @@ mono_domain_unload (MonoDomain *domain) MonoMethod *method; MonoObject *exc; unload_data thread_data; + MonoDomain *caller_domain = mono_domain_get (); /* printf ("UNLOAD STARTING FOR %s.\n", domain->friendly_name); */ @@ -1232,6 +1251,7 @@ mono_domain_unload (MonoDomain *domain) g_assert_not_reached (); } + mono_domain_set (domain, FALSE); /* Notify OnDomainUnload listeners */ method = look_for_method_by_name (domain->domain->mbr.obj.vtable->klass, "DoDomainUnload"); g_assert (method); @@ -1241,6 +1261,7 @@ mono_domain_unload (MonoDomain *domain) if (exc) { /* Roll back the state change */ domain->state = MONO_APPDOMAIN_CREATED; + mono_domain_set (caller_domain, FALSE); mono_raise_exception ((MonoException*)exc); } @@ -1267,6 +1288,7 @@ mono_domain_unload (MonoDomain *domain) ; /* wait for the thread */ + mono_domain_set (caller_domain, FALSE); if (thread_data.failure_reason) { MonoException *ex; diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c index 2ae0d0eef7b..a0ec7467f38 100644 --- a/mono/metadata/assembly.c +++ b/mono/metadata/assembly.c @@ -388,6 +388,15 @@ mono_assembly_load_references (MonoImage *image, MonoImageOpenStatus *status) image->name, aname.name); } else { + char *extra_msg = g_strdup (""); + + if (*status == MONO_IMAGE_ERROR_ERRNO) { + extra_msg = g_strdup_printf ("System error: %s\n", strerror (errno)); + } else if (*status == MONO_IMAGE_MISSING_ASSEMBLYREF) { + extra_msg = g_strdup ("Cannot find an assembly referenced from this one.\n"); + } else if (*status == MONO_IMAGE_IMAGE_INVALID) { + extra_msg = g_strdup ("The file exists but is not a valid assembly.\n"); + } for (j = 0; j < i; j++) mono_assembly_close (references [j]); @@ -396,11 +405,12 @@ mono_assembly_load_references (MonoImage *image, MonoImageOpenStatus *status) g_warning ("Could not find assembly %s, references from %s (assemblyref_index=%d)\n" " Major/Minor: %d,%d\n" " Build: %d,%d\n" - " Token: %s\n", + " Token: %s\n%s", aname.name, image->name, i, aname.major, aname.minor, aname.build, aname.revision, - aname.public_key_token); + aname.public_key_token, extra_msg); *status = MONO_IMAGE_MISSING_ASSEMBLYREF; + g_free (extra_msg); return; } } diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 7f434b5c734..2814e47d255 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -2124,7 +2124,7 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, class = mono_array_class_get (type->data.klass, 1); break; case MONO_TYPE_PTR: - class = mono_class_from_mono_type (type->data.type); + class = mono_ptr_class_get (type->data.type); break; case MONO_TYPE_GENERICINST: g_assert (type->data.generic_inst->klass); diff --git a/mono/metadata/culture-info-tables.h b/mono/metadata/culture-info-tables.h index 08698a4cb1e..bf0699633fe 100644 --- a/mono/metadata/culture-info-tables.h +++ b/mono/metadata/culture-info-tables.h @@ -1,12 +1,13 @@ -
-#ifndef MONO_METADATA_CULTURE_INFO_TABLES
-#define MONO_METADATA_CULTURE_INFO_TABLES 1
-
-#define NUM_CULTURE_ENTRIES 154
+#ifndef MONO_METADATA_CULTURE_INFO_TABLES +#define MONO_METADATA_CULTURE_INFO_TABLES 1 -
-static const DateTimeFormatEntry datetime_format_entries [] = {
+ +#define NUM_CULTURE_ENTRIES 155 + + +static const DateTimeFormatEntry datetime_format_entries [] = { + {"d MMMM, yyyy h:mm:ss t", "d MMMM, yyyy", "d/M/yyyy", "h:mm:ss t", "h:mm t", "MMMM, yyyy", "d MMMM", "\xd8\xb5", "\xd9\x85", {"\xd8\xa7\xd9\x84\xd8\xa3\xd8\xad\xd8\xaf", "\xd8\xa7\xd9\x84\xd8\xa7\xd8\xab\xd9\x86\xd9\x8a\xd9\x86", "\xd8\xa7\xd9\x84\xd8\xab\xd9\x84\xd8\xa7\xd8\xab\xd8\xa7\xd8\xa1", "\xd8\xa7\xd9\x84\xd8\xa3\xd8\xb1\xd8\xa8\xd8\xb9\xd8\xa7\xd8\xa1", "\xd8\xa7\xd9\x84\xd8\xae\xd9\x85\xd9\x8a\xd8\xb3", "\xd8\xa7\xd9\x84\xd8\xac\xd9\x85\xd8\xb9\xd8\xa9", "\xd8\xa7\xd9\x84\xd8\xb3\xd8\xa8\xd8\xaa"}, {"\xd8\xa7\xd9\x84\xd8\xa3\xd8\xad\xd8\xaf", "\xd8\xa7\xd9\x84\xd8\xa7\xd8\xab\xd9\x86\xd9\x8a\xd9\x86", "\xd8\xa7\xd9\x84\xd8\xab\xd9\x84\xd8\xa7\xd8\xab\xd8\xa7\xd8\xa1", "\xd8\xa7\xd9\x84\xd8\xa3\xd8\xb1\xd8\xa8\xd8\xb9\xd8\xa7\xd8\xa1", "\xd8\xa7\xd9\x84\xd8\xae\xd9\x85\xd9\x8a\xd8\xb3", "\xd8\xa7\xd9\x84\xd8\xac\xd9\x85\xd8\xb9\xd8\xa9", "\xd8\xa7\xd9\x84\xd8\xb3\xd8\xa8\xd8\xaa"}, {"\xd9\x8a\xd9\x86\xd8\xa7\xd9\x8a\xd8\xb1", "\xd9\x81\xd8\xa8\xd8\xb1\xd8\xa7\xd9\x8a\xd8\xb1", "\xd9\x85\xd8\xa7\xd8\xb1\xd8\xb3", "\xd8\xa3\xd8\xa8\xd8\xb1\xd9\x8a\xd9\x84", "\xd9\x85\xd8\xa7\xd9\x8a\xd9\x88", "\xd9\x8a\xd9\x88\xd9\x86\xd9\x8a\xd9\x88", "\xd9\x8a\xd9\x88\xd9\x84\xd9\x8a\xd9\x88", "\xd8\xa3\xd8\xba\xd8\xb3\xd8\xb7\xd8\xb3", "\xd8\xb3\xd8\xa8\xd8\xaa\xd9\x85\xd8\xa8\xd8\xb1", "\xd8\xa3\xd9\x83\xd8\xaa\xd9\x88\xd8\xa8\xd8\xb1", "\xd9\x86\xd9\x88\xd9\x81\xd9\x85\xd8\xa8\xd8\xb1", "\xd8\xaf\xd9\x8a\xd8\xb3\xd9\x85\xd8\xa8\xd8\xb1"}, {"\xd9\x8a\xd9\x86\xd8\xa7\xd9\x8a\xd8\xb1", "\xd9\x81\xd8\xa8\xd8\xb1\xd8\xa7\xd9\x8a\xd8\xb1", "\xd9\x85\xd8\xa7\xd8\xb1\xd8\xb3", "\xd8\xa3\xd8\xa8\xd8\xb1\xd9\x8a\xd9\x84", "\xd9\x85\xd8\xa7\xd9\x8a\xd9\x88", "\xd9\x8a\xd9\x88\xd9\x86\xd9\x8a\xd9\x88", "\xd9\x8a\xd9\x88\xd9\x84\xd9\x8a\xd9\x88", "\xd8\xa3\xd8\xba\xd8\xb3\xd8\xb7\xd8\xb3", "\xd8\xb3\xd8\xa8\xd8\xaa\xd9\x85\xd8\xa8\xd8\xb1", "\xd8\xa3\xd9\x83\xd8\xaa\xd9\x88\xd8\xa8\xd8\xb1", "\xd9\x86\xd9\x88\xd9\x81\xd9\x85\xd8\xa8\xd8\xb1", "\xd8\xaf\xd9\x8a\xd8\xb3\xd9\x85\xd8\xa8\xd8\xb1", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"dd MMMM yyyy HH:mm:ss", "dd MMMM yyyy", "dd.M.yyyy '\xd0\xb3.'", "HH:mm:ss", "HH:mm", "MMMM yyyy", "dd MMMM", "AM", "PM", {"\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd1\x8f", "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xbd\xd0\xb8\xd0\xba", "\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80\xd0\xbd\xd0\xb8\xd0\xba", "\xd1\x81\xd1\x80\xd1\x8f\xd0\xb4\xd0\xb0", "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd1\x8a\xd1\x80\xd1\x82\xd1\x8a\xd0\xba", "\xd0\xbf\xd0\xb5\xd1\x82\xd1\x8a\xd0\xba", "\xd1\x81\xd1\x8a\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0"}, {"\xd0\xbd\xd0\xb5\xd0\xb4.", "\xd0\xbf\xd0\xbe\xd0\xbd.", "\xd0\xb2\xd1\x82.", "\xd1\x81\xd1\x80.", "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2.", "\xd0\xbf\xd0\xb5\xd1\x82.", "\xd1\x81\xd1\x8a\xd0\xb1."}, {"\xd1\x8f\xd0\xbd\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8", "\xd1\x84\xd0\xb5\xd0\xb2\xd1\x80\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8", "\xd0\xbc\xd0\xb0\xd1\x80\xd1\x82", "\xd0\xb0\xd0\xbf\xd1\x80\xd0\xb8\xd0\xbb", "\xd0\xbc\xd0\xb0\xd0\xb9", "\xd1\x8e\xd0\xbd\xd0\xb8", "\xd1\x8e\xd0\xbb\xd0\xb8", "\xd0\xb0\xd0\xb2\xd0\xb3\xd1\x83\xd1\x81\xd1\x82", "\xd1\x81\xd0\xb5\xd0\xbf\xd1\x82\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8", "\xd0\xbe\xd0\xba\xd1\x82\xd0\xbe\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8", "\xd0\xbd\xd0\xbe\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8", "\xd0\xb4\xd0\xb5\xd0\xba\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8"}, {"\xd1\x8f\xd0\xbd.", "\xd1\x84\xd0\xb5\xd0\xb2.", "\xd0\xbc\xd0\xb0\xd1\x80\xd1\x82", "\xd0\xb0\xd0\xbf\xd1\x80.", "\xd0\xbc\xd0\xb0\xd0\xb9", "\xd1\x8e\xd0\xbd\xd0\xb8", "\xd1\x8e\xd0\xbb\xd0\xb8", "\xd0\xb0\xd0\xb2\xd0\xb3.", "\xd1\x81\xd0\xb5\xd0\xbf.", "\xd0\xbe\xd0\xba\xd1\x82.", "\xd0\xbd\xd0\xbe\xd0\xb5\xd0\xbc.", "\xd0\xb4\xd0\xb5\xd0\xba.", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"d MMMM yyyy HH:mm:ss z", "d MMMM yyyy", "dd/MM/yyyy", "HH:mm:ss", "HH:mm", "MMMM yyyy", "dd MMMM", "AM", "PM", {"diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"}, {"dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."}, {"gener", "febrer", "mar\xc3\xa7", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"}, {"gen.", "feb.", "mar\xc3\xa7", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des.", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"d. MMMM yyyy H:mm:ss z", "d. MMMM yyyy", "d.M.yyyy", "H:mm:ss", "H:mm", "MMMM yyyy", "d. MMMM", "dop.", "odp.", {"ned\xc4\x9ble", "pond\xc4\x9bl\xc3\xad", "\xc3\xbater\xc3\xbd", "st\xc5\x99\x65\x64\x61", "\xc4\x8dtvrtek", "p\xc3\xa1tek", "sobota"}, {"ne", "po", "\xc3\xbat", "st", "\xc4\x8dt", "p\xc3\xa1", "so"}, {"leden", "\xc3\xbanor", "b\xc5\x99\x65zen", "duben", "kv\xc4\x9bten", "\xc4\x8d\x65rven", "\xc4\x8d\x65rvenec", "srpen", "z\xc3\xa1\xc5\x99\xc3\xad", "\xc5\x99\xc3\xadjen", "listopad", "prosinec"}, {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, @@ -20,10 +21,10 @@ static const DateTimeFormatEntry datetime_format_entries [] = { {"yyyy. MMMM d. H:mm:ss z", "yyyy. MMMM d.", "yyyy. MM. dd.", "H:mm:ss", "H:mm", "yyyy. MMMM", "MMMM d", "DE", "DU", {"vas\xc3\xa1rnap", "h\xc3\xa9tf\xc5\x91", "kedd", "szerda", "cs\xc3\xbct\xc3\xb6rt\xc3\xb6k", "p\xc3\xa9ntek", "szombat"}, {"V", "H", "K", "Sze", "Cs", "P", "Szo"}, {"janu\xc3\xa1r", "febru\xc3\xa1r", "m\xc3\xa1rcius", "\xc3\xa1prilis", "m\xc3\xa1jus", "j\xc3\xbanius", "j\xc3\xbalius", "augusztus", "szeptember", "okt\xc3\xb3\x62\x65r", "november", "december"}, {"jan.", "febr.", "m\xc3\xa1rc.", "\xc3\xa1pr.", "m\xc3\xa1j.", "j\xc3\xban.", "j\xc3\xbal.", "aug.", "szept.", "okt.", "nov.", "dec.", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"d. MMMM yyyy HH:mm:ss z", "d. MMMM yyyy", "d.M.yyyy", "HH:mm:ss", "HH:mm", "MMMM yyyy", "d. MMMM", "AM", "PM", {"sunnudagur", "m\xc3\xa1nudagur", "\xc3\xberi\xc3\xb0judagur", "mi\xc3\xb0vikudagur", "fimmtudagur", "f\xc3\xb6studagur", "laugardagur"}, {"sun", "m\xc3\xa1n", "\xc3\xberi", "mi\xc3\xb0", "fim", "f\xc3\xb6s", "lau"}, {"jan\xc3\xba\x61r", "febr\xc3\xba\x61r", "mars", "apr\xc3\xadl", "ma\xc3\xad", "j\xc3\xban\xc3\xad", "j\xc3\xbal\xc3\xad", "\xc3\xa1g\xc3\xbast", "september", "okt\xc3\xb3\x62\x65r", "n\xc3\xb3vember", "desember"}, {"jan", "feb", "mar", "apr", "ma\xc3\xad", "j\xc3\xban", "j\xc3\xbal", "\xc3\xa1g\xc3\xba", "sep", "okt", "n\xc3\xb3v", "des", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"dd MMMM yyyy H:mm:ss z", "dd MMMM yyyy", "dd/MM/yyyy", "H.mm.ss", "HH:mm", "MMMM yyyy", "d MMMM", "m.", "p.", {"domenica", "luned\xc3\xac", "marted\xc3\xac", "mercoled\xc3\xac", "gioved\xc3\xac", "venerd\xc3\xac", "sabato"}, {"dom", "lun", "mar", "mer", "gio", "ven", "sab"}, {"gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"}, {"gen", "feb", "mar", "apr", "mag", "giu", "lug", "ago", "set", "ott", "nov", "dic", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, - {"yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' H:mm:ss", "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'", "yyyy/MM/dd", "H:mm:ss", "H:mm", "yyyy'\xe5\xb9\xb4'M", "M'\xe6\x9c\x88'd", "\xe5\x8d\x88\xe5\x89\x8d", "\xe5\x8d\x88\xe5\xbe\x8c", {"\xe6\x97\xa5\xe6\x9b\x9c\xe6\x97\xa5", "\xe6\x9c\x88\xe6\x9b\x9c\xe6\x97\xa5", "\xe7\x81\xab\xe6\x9b\x9c\xe6\x97\xa5", "\xe6\xb0\xb4\xe6\x9b\x9c\xe6\x97\xa5", "\xe6\x9c\xa8\xe6\x9b\x9c\xe6\x97\xa5", "\xe9\x87\x91\xe6\x9b\x9c\xe6\x97\xa5", "\xe5\x9c\x9f\xe6\x9b\x9c\xe6\x97\xa5"}, {"\xe6\x97\xa5", "\xe6\x9c\x88", "\xe7\x81\xab", "\xe6\xb0\xb4", "\xe6\x9c\xa8", "\xe9\x87\x91", "\xe5\x9c\x9f"}, {"1\xe6\x9c\x88", "2\xe6\x9c\x88", "3\xe6\x9c\x88", "4\xe6\x9c\x88", "5\xe6\x9c\x88", "6\xe6\x9c\x88", "7\xe6\x9c\x88", "8\xe6\x9c\x88", "9\xe6\x9c\x88", "10\xe6\x9c\x88", "11\xe6\x9c\x88", "12\xe6\x9c\x88"}, {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", ""}, 0, 0, "/", ":", {"yyyy/MM/dd","yy/MM/dd","yy/M/d","yyyy/M/d","yy/MM/dd' ('ddd')'","yy/M/d' ('ddd')'","yyyy/M/d' ('ddd')'"},{"yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'","yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5'","yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' dddd","yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5' dddd"},{"H:mm","HH:mm","tt h:mm","tt hh:mm"},{"H:mm:ss","HH:mm:ss","tt h:mm:ss","tt hh:mm:ss"}}, + {"yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' H:mm:ss:z", "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'", "yyyy/MM/dd", "H:mm:ss:z", "H:mm", "yyyy'\xe5\xb9\xb4'M", "M'\xe6\x9c\x88'd", "\xe5\x8d\x88\xe5\x89\x8d", "\xe5\x8d\x88\xe5\xbe\x8c", {"\xe6\x97\xa5\xe6\x9b\x9c\xe6\x97\xa5", "\xe6\x9c\x88\xe6\x9b\x9c\xe6\x97\xa5", "\xe7\x81\xab\xe6\x9b\x9c\xe6\x97\xa5", "\xe6\xb0\xb4\xe6\x9b\x9c\xe6\x97\xa5", "\xe6\x9c\xa8\xe6\x9b\x9c\xe6\x97\xa5", "\xe9\x87\x91\xe6\x9b\x9c\xe6\x97\xa5", "\xe5\x9c\x9f\xe6\x9b\x9c\xe6\x97\xa5"}, {"\xe6\x97\xa5", "\xe6\x9c\x88", "\xe7\x81\xab", "\xe6\xb0\xb4", "\xe6\x9c\xa8", "\xe9\x87\x91", "\xe5\x9c\x9f"}, {"1\xe6\x9c\x88", "2\xe6\x9c\x88", "3\xe6\x9c\x88", "4\xe6\x9c\x88", "5\xe6\x9c\x88", "6\xe6\x9c\x88", "7\xe6\x9c\x88", "8\xe6\x9c\x88", "9\xe6\x9c\x88", "10\xe6\x9c\x88", "11\xe6\x9c\x88", "12\xe6\x9c\x88"}, {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", ""}, 0, 0, "/", ":", {"yyyy/MM/dd","yy/MM/dd","yy/M/d","yyyy/M/d","yy/MM/dd' ('ddd')'","yy/M/d' ('ddd')'","yyyy/M/d' ('ddd')'"},{"yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'","yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5'","yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' dddd","yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5' dddd"},{"H:mm","HH:mm","tt h:mm","tt hh:mm"},{"H:mm:ss","HH:mm:ss","tt h:mm:ss","tt hh:mm:ss"}}, {"yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc' t hh'\xec\x8b\x9c' mm'\xeb\xb6\x84' ss'\xec\xb4\x88'", "yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc'", "yyyy-MM-dd tt", "h:mm:ss", "t h:mm", "yyyy'\xeb\x85\x84' M", "M'\xec\x9b\x94' d", "\xec\x98\xa4\xec\xa0\x84", "\xec\x98\xa4\xed\x9b\x84", {"\xec\x9d\xbc\xec\x9a\x94\xec\x9d\xbc", "\xec\x9b\x94\xec\x9a\x94\xec\x9d\xbc", "\xed\x99\x94\xec\x9a\x94\xec\x9d\xbc", "\xec\x88\x98\xec\x9a\x94\xec\x9d\xbc", "\xeb\xaa\xa9\xec\x9a\x94\xec\x9d\xbc", "\xea\xb8\x88\xec\x9a\x94\xec\x9d\xbc", "\xed\x86\xa0\xec\x9a\x94\xec\x9d\xbc"}, {"\xec\x9d\xbc", "\xec\x9b\x94", "\xed\x99\x94", "\xec\x88\x98", "\xeb\xaa\xa9", "\xea\xb8\x88", "\xed\x86\xa0"}, {"1\xec\x9b\x94", "2\xec\x9b\x94", "3\xec\x9b\x94", "4\xec\x9b\x94", "5\xec\x9b\x94", "6\xec\x9b\x94", "7\xec\x9b\x94", "8\xec\x9b\x94", "9\xec\x9b\x94", "10\xec\x9b\x94", "11\xec\x9b\x94", "12\xec\x9b\x94"}, {"1\xec\x9b\x94", "2\xec\x9b\x94", "3\xec\x9b\x94", "4\xec\x9b\x94", "5\xec\x9b\x94", "6\xec\x9b\x94", "7\xec\x9b\x94", "8\xec\x9b\x94", "9\xec\x9b\x94", "10\xec\x9b\x94", "11\xec\x9b\x94", "12\xec\x9b\x94", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"d MMMM yyyy H:mm:ss z", "d MMMM yyyy", "d-M-yyyy", "H:mm:ss", "H:mm", "MMMM yyyy", "d MMMM", "AM", "PM", {"zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"}, {"zo", "ma", "di", "wo", "do", "vr", "za"}, {"januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"}, {"jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, - {"d MMMM yyyy HH:mm:ss z", "d MMMM yyyy", "yyyy-MM-dd", "HH:mm:ss", "HH:mm", "MMMM yyyy", "d MMMM", "AM", "PM", {"niedziela", "poniedzia?ek", "wtorek", "?roda", "czwartek", "pi?tek", "sobota"}, {"N", "Pn", "Wt", "?r", "Cz", "Pt", "So"}, {"stycze?", "luty", "marzec", "kwiecie?", "maj", "czerwiec", "lipiec", "sierpie?", "wrzesie?", "pa?dziernik", "listopad", "grudzie?"}, {"sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "pa?", "lis", "gru", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, + {"d MMMM yyyy HH:mm:ss z", "d MMMM yyyy", "yyyy-MM-dd", "HH:mm:ss", "HH:mm", "MMMM yyyy", "d MMMM", "AM", "PM", {"niedziela", "poniedzia\xc5\x82\x65k", "wtorek", "\xc5\x9broda", "czwartek", "pi\xc4\x85tek", "sobota"}, {"N", "Pn", "Wt", "\xc5\x9ar", "Cz", "Pt", "So"}, {"stycze\xc5\x84", "luty", "marzec", "kwiecie\xc5\x84", "maj", "czerwiec", "lipiec", "sierpie\xc5\x84", "wrzesie\xc5\x84", "pa\xc5\xba\x64ziernik", "listopad", "grudzie\xc5\x84"}, {"sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "pa\xc5\xba", "lis", "gru", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"d' de 'MMMM' de 'yyyy H'h'm'min's's' z", "d' de 'MMMM' de 'yyyy", "d/M/yyyy", "HH:mm:ss", "HH:mm", "MMMM' de 'yyyy", "d' de 'MMMM", "AM", "PM", {"domingo", "segunda-feira", "ter\xc3\xa7\x61-feira", "quarta-feira", "quinta-feira", "sexta-feira", "s\xc3\xa1\x62\x61\x64o"}, {"dom", "seg", "ter", "qua", "qui", "sex", "s\xc3\xa1\x62"}, {"janeiro", "fevereiro", "mar\xc3\xa7o", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"}, {"jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"d MMMM yyyy HH:mm:ss z", "d MMMM yyyy", "dd.MM.yyyy", "HH:mm:ss", "HH:mm", "MMMM yyyy", "d MMMM", "AM", "PM", {"duminic\xc4\x83", "luni", "mar\xc5\xa3i", "miercuri", "joi", "vineri", "s\xc3\xaemb\xc4\x83t\xc4\x83"}, {"D", "L", "Ma", "Mi", "J", "V", "S"}, {"ianuarie", "februarie", "martie", "aprilie", "mai", "iunie", "iulie", "august", "septembrie", "octombrie", "noiembrie", "decembrie"}, {"Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, {"d MMMM yyyy '\xd0\xb3.' H:mm:ss z", "d MMMM yyyy '\xd0\xb3.'", "dd.MM.yyyy", "H:mm:ss", "H:mm", "MMMM yyyy", "d MMMM", "AM", "PM", {"\xd0\xb2\xd0\xbe\xd1\x81\xd0\xba\xd1\x80\xd0\xb5\xd1\x81\xd0\xb5\xd0\xbd\xd1\x8c\xd0\xb5", "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd1\x8c\xd0\xbd\xd0\xb8\xd0\xba", "\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80\xd0\xbd\xd0\xb8\xd0\xba", "\xd1\x81\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb0", "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb3", "\xd0\xbf\xd1\x8f\xd1\x82\xd0\xbd\xd0\xb8\xd1\x86\xd0\xb0", "\xd1\x81\xd1\x83\xd0\xb1\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0"}, {"\xd0\x92\xd1\x81", "\xd0\x9f\xd0\xbd", "\xd0\x92\xd1\x82", "\xd0\xa1\xd1\x80", "\xd0\xa7\xd1\x82", "\xd0\x9f\xd1\x82", "\xd0\xa1\xd0\xb1"}, {"\xd0\xaf\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c", "\xd0\xa4\xd0\xb5\xd0\xb2\xd1\x80\xd0\xb0\xd0\xbb\xd1\x8c", "\xd0\x9c\xd0\xb0\xd1\x80\xd1\x82", "\xd0\x90\xd0\xbf\xd1\x80\xd0\xb5\xd0\xbb\xd1\x8c", "\xd0\x9c\xd0\xb0\xd0\xb9", "\xd0\x98\xd1\x8e\xd0\xbd\xd1\x8c", "\xd0\x98\xd1\x8e\xd0\xbb\xd1\x8c", "\xd0\x90\xd0\xb2\xd0\xb3\xd1\x83\xd1\x81\xd1\x82", "\xd0\xa1\xd0\xb5\xd0\xbd\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c", "\xd0\x9e\xd0\xba\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c", "\xd0\x9d\xd0\xbe\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c", "\xd0\x94\xd0\xb5\xd0\xba\xd0\xb0\xd0\xb1\xd1\x80\xd1\x8c"}, {"\xd1\x8f\xd0\xbd\xd0\xb2", "\xd1\x84\xd0\xb5\xd0\xb2", "\xd0\xbc\xd0\xb0\xd1\x80", "\xd0\xb0\xd0\xbf\xd1\x80", "\xd0\xbc\xd0\xb0\xd0\xb9", "\xd0\xb8\xd1\x8e\xd0\xbd", "\xd0\xb8\xd1\x8e\xd0\xbb", "\xd0\xb0\xd0\xb2\xd0\xb3", "\xd1\x81\xd0\xb5\xd0\xbd", "\xd0\xbe\xd0\xba\xd1\x82", "\xd0\xbd\xd0\xbe\xd1\x8f", "\xd0\xb4\xd0\xb5\xd0\xba", ""}, 0, 0, "/", ":", {0},{0},{0},{0}}, @@ -112,8 +113,9 @@ static const DateTimeFormatEntry datetime_format_entries [] = { {"d' de 'MMMM' de 'yyyy hh:mm:ss t z", "d' de 'MMMM' de 'yyyy", "dd/MM/yyyy", "hh:mm:ss tt", "hh:mm t", "MMMM' de 'yyyy", "d' de 'MMMM", "a.m.", "p.m.", {"domingo", "lunes", "martes", "mi\xc3\xa9rcoles", "jueves", "viernes", "s\xc3\xa1\x62\x61\x64o"}, {"dom", "lun", "mar", "mi\xc3\xa9", "jue", "vie", "s\xc3\xa1\x62"}, {"enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"}, {"ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic", ""}, 0, 0, "/", ":", {0},{0},{0},{0}} }; -
-static const NumberFormatEntry number_format_entries [] = {
+ +static const NumberFormatEntry number_format_entries [] = { + {"\xd9\xab", "\xd9\xac", "\xd9\xab", "\xd9\xac", "\xd9\xab", "\xd9\xac", "\xd8\xb1.\xd8\xb3.\xe2\x80\x8f", "\xd9\xaa", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 1, 0, 1, 1, 3, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {",", "\xc2\xa0", ",", "\xc2\xa0", ",", "\xc2\xa0", "\xd0\xbb\xd0\xb2.", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 8, 3, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {",", ".", ",", ".", ",", ".", "\xe2\x82\xac", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 8, 3, 0, 0, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {",", "\xc2\xa0", ",", "\xc2\xa0", ",", "\xc2\xa0", "K\xc4\x8d", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 8, 3, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, @@ -130,8 +132,8 @@ static const NumberFormatEntry number_format_entries [] = { {".", ",", ".", ",", ".", ",", "\\", "%", "NaN", "\xe2\x80\xb0", "-Infinity", "Infinity", "-", "+", 1, 0, 1, 1, 1, 0, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {".", ",", ".", ",", ".", ",", "\xef\xbf\xa6", "%", "NaN", "\xe2\x80\xb0", "-Infinity", "Infinity", "-", "+", 0, 0, 0, 0, 1, 0, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {",", ".", ",", ".", ",", ".", "\xe2\x82\xac", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 11, 2, 0, 0, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, - {",", "?", ",", "?", ",", "?", "z?", "%", "?", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 8, 3, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, - {",", ".", ",", ".", ",", ".", "R$", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 0, 0, 1, 1, 1, 0, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, + {",", "\xc2\xa0", ",", "\xc2\xa0", ",", "\xc2\xa0", "z\xc5\x82", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 8, 3, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, + {",", ".", ",", ".", ",", ".", "R$ ", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 0, 0, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {",", ".", ",", ".", ",", ".", "lei", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 8, 3, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {",", "\xc2\xa0", ",", "\xc2\xa0", ",", "\xc2\xa0", "\xd1\x80.", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 5, 1, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, {",", ".", ",", ".", ",", ".", "Kn", "%", "\xef\xbf\xbd", "\xe2\x80\xb0", "-\xe2\x88\x9e", "\xe2\x88\x9e", "-", "+", 9, 2, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}}, @@ -219,8 +221,8 @@ static const NumberFormatEntry number_format_entries [] = { {".", ",", ".", ",", ".", ",", "$", "%", "NaN", "\xe2\x80\xb0", "-Infinity", "Infinity", "-", "+", 0, 0, 1, 1, 1, 2, 2, 2, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}, {3, -1, -1, -1, -1}} }; -
-static const CultureInfoEntry culture_entries [] = {
+ +static const CultureInfoEntry culture_entries [] = { {0x0001, 0x007F, 0x0401, "ar", "Arabic", "Arabic", "Arabic", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9", "ARA", "ara", "ar", {0, 0, 0, 0, 0}, -1, -1}, {0x0002, 0x007F, 0x0402, "bg", "Bulgarian", "Bulgarian", "Bulgarian", "\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8", "BGR", "bul", "bg", {0, 0, 0, 0, 0}, -1, -1}, {0x0003, 0x007F, 0x0403, "ca", "Catalan", "Catalan", "Catalan", "catal\xc3\xa0", "CAT", "cat", "ca", {0, 0, 0, 0, 0}, -1, -1}, @@ -272,269 +274,271 @@ static const CultureInfoEntry culture_entries [] = { {0x004E, 0x007F, 0x044E, "mr", "Marathi", "Marathi", "Marathi", "\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80", "MAR", "mar", "mr", {0, 0, 0, 0, 0}, -1, -1}, {0x0056, 0x007F, 0x0456, "gl", "Gallegan", "Gallegan", "Gallegan", "galego", "GLC", "glg", "gl", {0, 0, 0, 0, 0}, -1, -1}, {0x0057, 0x007F, 0x0457, "kok", "Konkani", "Konkani", "Konkani", "\xe0\xa4\x95\xe0\xa5\x8b\xe0\xa4\x82\xe0\xa4\x95\xe0\xa4\xa3\xe0\xa5\x80", "KNK", "kok", "hi", {0, 0, 0, 0, 0}, -1, -1}, - {0x0402, 0x0002, 0x0402, "bg-BG", "Bulgarian (Bulgaria)", "Bulgarian (Bulgaria)", "Bulgarian (Bulgaria)", "\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd0\xb8\xd1\x8f)", "BGR", "bul", "bg", {0, 0, 0, 0, 0}, 0, 0}, - {0x0403, 0x0003, 0x0403, "ca-ES", "Catalan (Spain)", "Catalan (Spain)", "Catalan (Spain)", "catal\xc3\xa0 (Espanya)", "CAT", "cat", "ca", {0, 0, 0, 0, 0}, 1, 1}, - {0x0405, 0x0005, 0x0405, "cs-CZ", "Czech (Czech Republic)", "Czech (Czech Republic)", "Czech (Czech Republic)", "\xc4\x8c\x65\xc5\xa1tina (\xc4\x8c\x65sk\xc3\xa1 republika)", "CSY", "ces", "cs", {0, 0, 0, 0, 0}, 2, 2}, - {0x0406, 0x0006, 0x0406, "da-DK", "Danish (Denmark)", "Danish (Denmark)", "Danish (Denmark)", "Dansk (Danmark)", "DAN", "dan", "da", {0, 0, 0, 0, 0}, 3, 3}, - {0x0407, 0x0007, 0x0407, "de-DE", "German (Germany)", "German (Germany)", "German (Germany)", "Deutsch (Deutschland)", "DEU", "deu", "de", {0, 0, 0, 0, 0}, 4, 4}, - {0x0408, 0x0008, 0x0408, "el-GR", "Greek (Greece)", "Greek (Greece)", "Greek (Greece)", "\xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac (\xce\x95\xce\xbb\xce\xbb\xce\xac\xce\xb4\xce\xb1)", "ELL", "ell", "el", {0, 0, 0, 0, 0}, 5, 5}, - {0x0409, 0x0009, 0x0409, "en-US", "English (United States)", "English (United States)", "English (United States)", "English (United States)", "ENU", "eng", "en", {0, 0, 0, 0, 0}, 6, 6}, - {0x040B, 0x000B, 0x040B, "fi-FI", "Finnish (Finland)", "Finnish (Finland)", "Finnish (Finland)", "suomi (Suomi)", "FIN", "fin", "fi", {0, 0, 0, 0, 0}, 7, 7}, - {0x040C, 0x000C, 0x040C, "fr-FR", "French (France)", "French (France)", "French (France)", "fran\xc3\xa7\x61is (France)", "FRA", "fra", "fr", {0, 0, 0, 0, 0}, 8, 8}, - {0x040D, 0x000D, 0x040D, "he-IL", "Hebrew (Israel)", "Hebrew (Israel)", "Hebrew (Israel)", "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa (\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c)", "HEB", "heb", "he", {0, 0, 0, 0, 0}, 9, 9}, - {0x040E, 0x000E, 0x040E, "hu-HU", "Hungarian (Hungary)", "Hungarian (Hungary)", "Hungarian (Hungary)", "magyar (Magyarorsz\xc3\xa1g)", "HUN", "hun", "hu", {0, 0, 0, 0, 0}, 10, 10}, - {0x040F, 0x000F, 0x040F, "is-IS", "Icelandic (Iceland)", "Icelandic (Iceland)", "Icelandic (Iceland)", "\xc3\xadslenska (\xc3\x8dsland)", "ISL", "isl", "is", {0, 0, 0, 0, 0}, 11, 11}, - {0x0410, 0x0010, 0x0410, "it-IT", "Italian (Italy)", "Italian (Italy)", "Italian (Italy)", "italiano (Italia)", "ITA", "ita", "it", {0, 0, 0, 0, 0}, 12, 12}, - {0x0411, 0x0011, 0x0411, "ja-JP", "Japanese (Japan)", "Japanese (Japan)", "Japanese (Japan)", "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (\xe6\x97\xa5\xe6\x9c\xac)", "JPN", "jpn", "ja", {0, 0, 0, 0, 0}, 13, 13}, - {0x0412, 0x0012, 0x0412, "ko-KR", "Korean (South Korea)", "Korean (South Korea)", "Korean (South Korea)", "\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4 (\xeb\x8c\x80\xed\x95\x9c\xeb\xaf\xbc\xea\xb5\xad)", "KOR", "kor", "ko", {0, 0, 0, 0, 0}, 14, 14}, - {0x0413, 0x0013, 0x0413, "nl-NL", "Dutch (Netherlands)", "Dutch (Netherlands)", "Dutch (Netherlands)", "Nederlands (Nederland)", "NLD", "nld", "nl", {0, 0, 0, 0, 0}, 15, 15}, - {0x0415, 0x0015, 0x0415, "pl-PL", "Polish (Poland)", "Polish (Poland)", "Polish (Poland)", "polski (Polska)", "PLK", "pol", "pl", {0, 0, 0, 0, 0}, 16, 16}, - {0x0416, 0x0016, 0x0416, "pt-BR", "Portuguese (Brazil)", "Portuguese (Brazil)", "Portuguese (Brazil)", "portugu\xc3\xaas (Brasil)", "PTB", "por", "pt", {0, 0, 0, 0, 0}, 17, 17}, - {0x0418, 0x0018, 0x0418, "ro-RO", "Romanian (Romania)", "Romanian (Romania)", "Romanian (Romania)", "Rom\xc3\xa2n\xc4\x83 (Rom\xc3\xa2nia)", "ROM", "ron", "ro", {0, 0, 0, 0, 0}, 18, 18}, - {0x0419, 0x0019, 0x0419, "ru-RU", "Russian (Russia)", "Russian (Russia)", "Russian (Russia)", "\xd0\xa0\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 (\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f)", "RUS", "rus", "ru", {0, 0, 0, 0, 0}, 19, 19}, - {0x041A, 0x001A, 0x041A, "hr-HR", "Croatian (Croatia)", "Croatian (Croatia)", "Croatian (Croatia)", "hrvatski (Hrvatska)", "HRV", "hrv", "hr", {0, 0, 0, 0, 0}, 20, 20}, - {0x041B, 0x001B, 0x041B, "sk-SK", "Slovak (Slovakia)", "Slovak (Slovakia)", "Slovak (Slovakia)", "slovensk\xc3\xbd (Slovensk\xc3\xa1 republika)", "SKY", "slk", "sk", {0, 0, 0, 0, 0}, 21, 21}, - {0x041C, 0x001C, 0x041C, "sq-AL", "Albanian (Albania)", "Albanian (Albania)", "Albanian (Albania)", "shqipe (Shqip\xc3\xabria)", "SQI", "sqi", "sq", {0, 0, 0, 0, 0}, 22, 22}, - {0x041D, 0x001D, 0x041D, "sv-SE", "Swedish (Sweden)", "Swedish (Sweden)", "Swedish (Sweden)", "svenska (Sverige)", "SVE", "swe", "sv", {0, 0, 0, 0, 0}, 23, 23}, - {0x041E, 0x001E, 0x041E, "th-TH", "Thai (Thailand)", "Thai (Thailand)", "Thai (Thailand)", "\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2 (\xe0\xb8\x9b\xe0\xb8\xa3\xe0\xb8\xb0\xe0\xb9\x80\xe0\xb8\x97\xe0\xb8\xa8\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2)", "THA", "tha", "th", {0, 0, 0, 0, 0}, 24, 24}, - {0x041F, 0x001F, 0x041F, "tr-TR", "Turkish (Turkey)", "Turkish (Turkey)", "Turkish (Turkey)", "T\xc3\xbcrk\xc3\xa7\x65 (T\xc3\xbcrkiye)", "TRK", "tur", "tr", {0, 0, 0, 0, 0}, 25, 25}, - {0x0421, 0x0021, 0x0421, "id-ID", "Indonesian (Indonesia)", "Indonesian (Indonesia)", "Indonesian (Indonesia)", "Bahasa Indonesia (Indonesia)", "IND", "ind", "id", {0, 0, 0, 0, 0}, 26, 26}, - {0x0422, 0x0022, 0x0422, "uk-UA", "Ukrainian (Ukraine)", "Ukrainian (Ukraine)", "Ukrainian (Ukraine)", "\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0 (\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd0\xb0)", "UKR", "ukr", "uk", {0, 0, 0, 0, 0}, 27, 27}, - {0x0423, 0x0023, 0x0423, "be-BY", "Belarusian (Belarus)", "Belarusian (Belarus)", "Belarusian (Belarus)", "\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd1\x96 (\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd1\x8c)", "BEL", "bel", "be", {0, 0, 0, 0, 0}, 28, 28}, - {0x0424, 0x0024, 0x0424, "sl-SI", "Slovenian (Slovenia)", "Slovenian (Slovenia)", "Slovenian (Slovenia)", "Sloven\xc5\xa1\xc4\x8dina (Slovenija)", "SLV", "slv", "sl", {0, 0, 0, 0, 0}, 29, 29}, - {0x0425, 0x0025, 0x0425, "et-EE", "Estonian (Estonia)", "Estonian (Estonia)", "Estonian (Estonia)", "Eesti (Eesti)", "ETI", "est", "et", {0, 0, 0, 0, 0}, 30, 30}, - {0x0426, 0x0026, 0x0426, "lv-LV", "Latvian (Latvia)", "Latvian (Latvia)", "Latvian (Latvia)", "latvie\xc5\xa1u (Latvija)", "LVI", "lav", "lv", {0, 0, 0, 0, 0}, 31, 31}, - {0x0427, 0x0027, 0x0427, "lt-LT", "Lithuanian (Lithuania)", "Lithuanian (Lithuania)", "Lithuanian (Lithuania)", "Lietuvi\xc5\xb3 (Lietuva)", "LTH", "lit", "lt", {0, 0, 0, 0, 0}, 32, 32}, - {0x0429, 0x0029, 0x0429, "fa-IR", "Persian (Iran)", "Persian (Iran)", "Persian (Iran)", "\xd9\x81\xd8\xa7\xd8\xb1\xd8\xb3\xdb\x8c (\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86)", "FAR", "fas", "fa", {0, 0, 0, 0, 0}, 33, 33}, - {0x042A, 0x002A, 0x042A, "vi-VN", "Vietnamese (Vietnam)", "Vietnamese (Vietnam)", "Vietnamese (Vietnam)", "Ti\xe1\xba\xbfng Vi\xe1\xbb\x87t (Vi\xe1\xbb\x87t Nam)", "VIT", "vie", "vi", {0, 0, 0, 0, 0}, 34, 34}, - {0x042B, 0x002B, 0x042B, "hy-AM", "Armenian (Armenia)", "Armenian (Armenia)", "Armenian (Armenia)", "\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa7\xd5\xb6 (\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa1\xd5\xbd\xd5\xbf\xd5\xa1\xd5\xb6\xd5\xab \xd5\x80\xd5\xa1\xd5\xb6\xd6\x80\xd5\xa1\xd5\xba\xd5\xa5\xd5\xbf\xd5\xb8\xd6\x82\xd5\xa9\xd5\xab\xd6\x82\xd5\xb6)", "HYE", "hye", "hy", {0, 0, 0, 0, 0}, 35, 35}, + {0x0401, 0x0001, 0x0401, "ar-SA", "Arabic (Saudi Arabia)", "Arabic (Saudi Arabia)", "Arabic (Saudi Arabia)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9)", "ARA", "ara", "ar", {16777216, 0, 0, 0, 0}, 0, 0}, + {0x0402, 0x0002, 0x0402, "bg-BG", "Bulgarian (Bulgaria)", "Bulgarian (Bulgaria)", "Bulgarian (Bulgaria)", "\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd0\xb8\xd1\x8f)", "BGR", "bul", "bg", {0, 0, 0, 0, 0}, 1, 1}, + {0x0403, 0x0003, 0x0403, "ca-ES", "Catalan (Spain)", "Catalan (Spain)", "Catalan (Spain)", "catal\xc3\xa0 (Espanya)", "CAT", "cat", "ca", {0, 0, 0, 0, 0}, 2, 2}, + {0x0405, 0x0005, 0x0405, "cs-CZ", "Czech (Czech Republic)", "Czech (Czech Republic)", "Czech (Czech Republic)", "\xc4\x8c\x65\xc5\xa1tina (\xc4\x8c\x65sk\xc3\xa1 republika)", "CSY", "ces", "cs", {0, 0, 0, 0, 0}, 3, 3}, + {0x0406, 0x0006, 0x0406, "da-DK", "Danish (Denmark)", "Danish (Denmark)", "Danish (Denmark)", "Dansk (Danmark)", "DAN", "dan", "da", {0, 0, 0, 0, 0}, 4, 4}, + {0x0407, 0x0007, 0x0407, "de-DE", "German (Germany)", "German (Germany)", "German (Germany)", "Deutsch (Deutschland)", "DEU", "deu", "de", {0, 0, 0, 0, 0}, 5, 5}, + {0x0408, 0x0008, 0x0408, "el-GR", "Greek (Greece)", "Greek (Greece)", "Greek (Greece)", "\xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac (\xce\x95\xce\xbb\xce\xbb\xce\xac\xce\xb4\xce\xb1)", "ELL", "ell", "el", {0, 0, 0, 0, 0}, 6, 6}, + {0x0409, 0x0009, 0x0409, "en-US", "English (United States)", "English (United States)", "English (United States)", "English (United States)", "ENU", "eng", "en", {0, 0, 0, 0, 0}, 7, 7}, + {0x040B, 0x000B, 0x040B, "fi-FI", "Finnish (Finland)", "Finnish (Finland)", "Finnish (Finland)", "suomi (Suomi)", "FIN", "fin", "fi", {0, 0, 0, 0, 0}, 8, 8}, + {0x040C, 0x000C, 0x040C, "fr-FR", "French (France)", "French (France)", "French (France)", "fran\xc3\xa7\x61is (France)", "FRA", "fra", "fr", {0, 0, 0, 0, 0}, 9, 9}, + {0x040D, 0x000D, 0x040D, "he-IL", "Hebrew (Israel)", "Hebrew (Israel)", "Hebrew (Israel)", "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa (\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c)", "HEB", "heb", "he", {0, 0, 0, 0, 0}, 10, 10}, + {0x040E, 0x000E, 0x040E, "hu-HU", "Hungarian (Hungary)", "Hungarian (Hungary)", "Hungarian (Hungary)", "magyar (Magyarorsz\xc3\xa1g)", "HUN", "hun", "hu", {0, 0, 0, 0, 0}, 11, 11}, + {0x040F, 0x000F, 0x040F, "is-IS", "Icelandic (Iceland)", "Icelandic (Iceland)", "Icelandic (Iceland)", "\xc3\xadslenska (\xc3\x8dsland)", "ISL", "isl", "is", {0, 0, 0, 0, 0}, 12, 12}, + {0x0410, 0x0010, 0x0410, "it-IT", "Italian (Italy)", "Italian (Italy)", "Italian (Italy)", "italiano (Italia)", "ITA", "ita", "it", {0, 0, 0, 0, 0}, 13, 13}, + {0x0411, 0x0011, 0x0411, "ja-JP", "Japanese (Japan)", "Japanese (Japan)", "Japanese (Japan)", "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (\xe6\x97\xa5\xe6\x9c\xac)", "JPN", "jpn", "ja", {0, 0, 0, 0, 0}, 14, 14}, + {0x0412, 0x0012, 0x0412, "ko-KR", "Korean (South Korea)", "Korean (South Korea)", "Korean (South Korea)", "\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4 (\xeb\x8c\x80\xed\x95\x9c\xeb\xaf\xbc\xea\xb5\xad)", "KOR", "kor", "ko", {0, 0, 0, 0, 0}, 15, 15}, + {0x0413, 0x0013, 0x0413, "nl-NL", "Dutch (Netherlands)", "Dutch (Netherlands)", "Dutch (Netherlands)", "Nederlands (Nederland)", "NLD", "nld", "nl", {0, 0, 0, 0, 0}, 16, 16}, + {0x0415, 0x0015, 0x0415, "pl-PL", "Polish (Poland)", "Polish (Poland)", "Polish (Poland)", "polski (Polska)", "PLK", "pol", "pl", {0, 0, 0, 0, 0}, 17, 17}, + {0x0416, 0x0016, 0x0416, "pt-BR", "Portuguese (Brazil)", "Portuguese (Brazil)", "Portuguese (Brazil)", "portugu\xc3\xaas (Brasil)", "PTB", "por", "pt", {0, 0, 0, 0, 0}, 18, 18}, + {0x0418, 0x0018, 0x0418, "ro-RO", "Romanian (Romania)", "Romanian (Romania)", "Romanian (Romania)", "Rom\xc3\xa2n\xc4\x83 (Rom\xc3\xa2nia)", "ROM", "ron", "ro", {0, 0, 0, 0, 0}, 19, 19}, + {0x0419, 0x0019, 0x0419, "ru-RU", "Russian (Russia)", "Russian (Russia)", "Russian (Russia)", "\xd0\xa0\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 (\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f)", "RUS", "rus", "ru", {0, 0, 0, 0, 0}, 20, 20}, + {0x041A, 0x001A, 0x041A, "hr-HR", "Croatian (Croatia)", "Croatian (Croatia)", "Croatian (Croatia)", "hrvatski (Hrvatska)", "HRV", "hrv", "hr", {0, 0, 0, 0, 0}, 21, 21}, + {0x041B, 0x001B, 0x041B, "sk-SK", "Slovak (Slovakia)", "Slovak (Slovakia)", "Slovak (Slovakia)", "slovensk\xc3\xbd (Slovensk\xc3\xa1 republika)", "SKY", "slk", "sk", {0, 0, 0, 0, 0}, 22, 22}, + {0x041C, 0x001C, 0x041C, "sq-AL", "Albanian (Albania)", "Albanian (Albania)", "Albanian (Albania)", "shqipe (Shqip\xc3\xabria)", "SQI", "sqi", "sq", {0, 0, 0, 0, 0}, 23, 23}, + {0x041D, 0x001D, 0x041D, "sv-SE", "Swedish (Sweden)", "Swedish (Sweden)", "Swedish (Sweden)", "svenska (Sverige)", "SVE", "swe", "sv", {0, 0, 0, 0, 0}, 24, 24}, + {0x041E, 0x001E, 0x041E, "th-TH", "Thai (Thailand)", "Thai (Thailand)", "Thai (Thailand)", "\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2 (\xe0\xb8\x9b\xe0\xb8\xa3\xe0\xb8\xb0\xe0\xb9\x80\xe0\xb8\x97\xe0\xb8\xa8\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2)", "THA", "tha", "th", {0, 0, 0, 0, 0}, 25, 25}, + {0x041F, 0x001F, 0x041F, "tr-TR", "Turkish (Turkey)", "Turkish (Turkey)", "Turkish (Turkey)", "T\xc3\xbcrk\xc3\xa7\x65 (T\xc3\xbcrkiye)", "TRK", "tur", "tr", {0, 0, 0, 0, 0}, 26, 26}, + {0x0421, 0x0021, 0x0421, "id-ID", "Indonesian (Indonesia)", "Indonesian (Indonesia)", "Indonesian (Indonesia)", "Bahasa Indonesia (Indonesia)", "IND", "ind", "id", {0, 0, 0, 0, 0}, 27, 27}, + {0x0422, 0x0022, 0x0422, "uk-UA", "Ukrainian (Ukraine)", "Ukrainian (Ukraine)", "Ukrainian (Ukraine)", "\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0 (\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd0\xb0)", "UKR", "ukr", "uk", {0, 0, 0, 0, 0}, 28, 28}, + {0x0423, 0x0023, 0x0423, "be-BY", "Belarusian (Belarus)", "Belarusian (Belarus)", "Belarusian (Belarus)", "\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd1\x96 (\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd1\x8c)", "BEL", "bel", "be", {0, 0, 0, 0, 0}, 29, 29}, + {0x0424, 0x0024, 0x0424, "sl-SI", "Slovenian (Slovenia)", "Slovenian (Slovenia)", "Slovenian (Slovenia)", "Sloven\xc5\xa1\xc4\x8dina (Slovenija)", "SLV", "slv", "sl", {0, 0, 0, 0, 0}, 30, 30}, + {0x0425, 0x0025, 0x0425, "et-EE", "Estonian (Estonia)", "Estonian (Estonia)", "Estonian (Estonia)", "Eesti (Eesti)", "ETI", "est", "et", {0, 0, 0, 0, 0}, 31, 31}, + {0x0426, 0x0026, 0x0426, "lv-LV", "Latvian (Latvia)", "Latvian (Latvia)", "Latvian (Latvia)", "latvie\xc5\xa1u (Latvija)", "LVI", "lav", "lv", {0, 0, 0, 0, 0}, 32, 32}, + {0x0427, 0x0027, 0x0427, "lt-LT", "Lithuanian (Lithuania)", "Lithuanian (Lithuania)", "Lithuanian (Lithuania)", "Lietuvi\xc5\xb3 (Lietuva)", "LTH", "lit", "lt", {0, 0, 0, 0, 0}, 33, 33}, + {0x0429, 0x0029, 0x0429, "fa-IR", "Persian (Iran)", "Persian (Iran)", "Persian (Iran)", "\xd9\x81\xd8\xa7\xd8\xb1\xd8\xb3\xdb\x8c (\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86)", "FAR", "fas", "fa", {0, 0, 0, 0, 0}, 34, 34}, + {0x042A, 0x002A, 0x042A, "vi-VN", "Vietnamese (Vietnam)", "Vietnamese (Vietnam)", "Vietnamese (Vietnam)", "Ti\xe1\xba\xbfng Vi\xe1\xbb\x87t (Vi\xe1\xbb\x87t Nam)", "VIT", "vie", "vi", {0, 0, 0, 0, 0}, 35, 35}, {0x042B, 0x002B, 0x042B, "hy-AM", "Armenian (Armenia)", "Armenian (Armenia)", "Armenian (Armenia)", "\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa7\xd5\xb6 (\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa1\xd5\xbd\xd5\xbf\xd5\xa1\xd5\xb6\xd5\xab \xd5\x80\xd5\xa1\xd5\xb6\xd6\x80\xd5\xa1\xd5\xba\xd5\xa5\xd5\xbf\xd5\xb8\xd6\x82\xd5\xa9\xd5\xab\xd6\x82\xd5\xb6)", "HYE", "hye", "hy", {0, 0, 0, 0, 0}, 36, 36}, - {0x042D, 0x002D, 0x042D, "eu-ES", "Basque (Spain)", "Basque (Spain)", "Basque (Spain)", "euskara (Espainia)", "EUQ", "eus", "eu", {0, 0, 0, 0, 0}, 37, 37}, - {0x042F, 0x002F, 0x042F, "mk-MK", "Macedonian (Macedonia)", "Macedonian (Macedonia)", "Macedonian (Macedonia)", "\xd0\xbc\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x9c\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd0\xb8\xd1\x98\xd0\xb0)", "MKI", "mkd", "mk", {0, 0, 0, 0, 0}, 38, 38}, - {0x0436, 0x0036, 0x0436, "af-ZA", "Afrikaans (South Africa)", "Afrikaans (South Africa)", "Afrikaans (South Africa)", "Afrikaanse (Suid-Afrika)", "AFK", "afr", "af", {0, 0, 0, 0, 0}, 39, 39}, - {0x0438, 0x0038, 0x0438, "fo-FO", "Faroese (Faroe Islands)", "Faroese (Faroe Islands)", "Faroese (Faroe Islands)", "f\xc3\xb8royskt (F\xc3\xb8royar)", "FOS", "fao", "fo", {0, 0, 0, 0, 0}, 40, 40}, - {0x0439, 0x0039, 0x0439, "hi-IN", "Hindi (India)", "Hindi (India)", "Hindi (India)", "\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)", "HIN", "hin", "hi", {0, 0, 0, 0, 0}, 41, 41}, - {0x0441, 0x0041, 0x0441, "sw-KE", "Swahili (Kenya)", "Swahili (Kenya)", "Swahili (Kenya)", "Kiswahili (Kenya)", "SWK", "swa", "sw", {0, 0, 0, 0, 0}, 42, 42}, - {0x0447, 0x0047, 0x0447, "gu-IN", "Gujarati (India)", "Gujarati (India)", "Gujarati (India)", "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\x9c\xe0\xaa\xb0\xe0\xaa\xbe\xe0\xaa\xa4\xe0\xab\x80 (\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4)", "GUJ", "guj", "gu", {0, 0, 0, 0, 0}, 43, 43}, - {0x0449, 0x0049, 0x0449, "ta-IN", "Tamil (India)", "Tamil (India)", "Tamil (India)", "\xe0\xae\xa4\xe0\xae\xae\xe0\xae\xbf\xe0\xae\xb4\xe0\xaf\x8d (\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe)", "TAM", "tam", "ta", {0, 0, 0, 0, 0}, 44, 44}, - {0x044A, 0x004A, 0x044A, "te-IN", "Telugu (India)", "Telugu (India)", "Telugu (India)", "\xe0\xb0\xa4\xe0\xb1\x86\xe0\xb0\xb2\xe0\xb1\x81\xe0\xb0\x97\xe0\xb1\x81 (\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4 \xe0\xb0\xa6\xe0\xb1\x87\xe0\xb0\xb3\xe0\xb1\xa6)", "TEL", "tel", "te", {0, 0, 0, 0, 0}, 45, 45}, - {0x044B, 0x004B, 0x044B, "kn-IN", "Kannada (India)", "Kannada (India)", "Kannada (India)", "\xe0\xb2\x95\xe0\xb2\xa8\xe0\xb3\x8d\xe0\xb2\xa8\xe0\xb2\xa1 (\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4)", "KAN", "kan", "kn", {0, 0, 0, 0, 0}, 46, 46}, - {0x044E, 0x004E, 0x044E, "mr-IN", "Marathi (India)", "Marathi (India)", "Marathi (India)", "\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)", "MAR", "mar", "mr", {0, 0, 0, 0, 0}, 47, 47}, - {0x0456, 0x0056, 0x0456, "gl-ES", "Gallegan (Spain)", "Gallegan (Spain)", "Gallegan (Spain)", "galego (Espa\xc3\xb1\x61)", "GLC", "glg", "gl", {0, 0, 0, 0, 0}, 48, 48}, - {0x0457, 0x0057, 0x0457, "kok-IN", "Konkani (India)", "Konkani (India)", "Konkani (India)", "\xe0\xa4\x95\xe0\xa5\x8b\xe0\xa4\x82\xe0\xa4\x95\xe0\xa4\xa3\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)", "KNK", "kok", "kok", {0, 0, 0, 0, 0}, 49, 49}, - {0x0801, 0x0001, 0x0801, "ar-IQ", "Arabic (Iraq)", "Arabic (Iraq)", "Arabic (Iraq)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82)", "ARI", "ara", "ar", {2, 1, 0, 0, 0}, 50, 50}, - {0x0807, 0x0007, 0x0807, "de-CH", "German (Switzerland)", "German (Switzerland)", "German (Switzerland)", "Deutsch (Schweiz)", "DES", "deu", "de", {0, 0, 0, 0, 0}, 51, 51}, - {0x0809, 0x0009, 0x0809, "en-GB", "English (United Kingdom)", "English (United Kingdom)", "English (United Kingdom)", "English (United Kingdom)", "ENG", "eng", "en", {0, 0, 0, 0, 0}, 52, 52}, - {0x080A, 0x000A, 0x080A, "es-MX", "Spanish (Mexico)", "Spanish (Mexico)", "Spanish (Mexico)", "espa\xc3\xb1ol (M\xc3\xa9xico)", "ESM", "spa", "es", {0, 0, 0, 0, 0}, 53, 53}, - {0x080C, 0x000C, 0x080C, "fr-BE", "French (Belgium)", "French (Belgium)", "French (Belgium)", "fran\xc3\xa7\x61is (Belgique)", "FRB", "fra", "fr", {0, 0, 0, 0, 0}, 54, 54}, - {0x0810, 0x0010, 0x0810, "it-CH", "Italian (Switzerland)", "Italian (Switzerland)", "Italian (Switzerland)", "italiano (Svizzera)", "ITS", "ita", "it", {0, 0, 0, 0, 0}, 55, 55}, - {0x0813, 0x0013, 0x0813, "nl-BE", "Dutch (Belgium)", "Dutch (Belgium)", "Dutch (Belgium)", "Nederlands (Belgi\xc3\xab)", "NLB", "nld", "nl", {0, 0, 0, 0, 0}, 56, 56}, - {0x0816, 0x0016, 0x0816, "pt-PT", "Portuguese (Portugal)", "Portuguese (Portugal)", "Portuguese (Portugal)", "portugu\xc3\xaas (Portugal)", "PTG", "por", "pt", {0, 0, 0, 0, 0}, 57, 57}, - {0x081D, 0x001D, 0x081D, "sv-FI", "Swedish (Finland)", "Swedish (Finland)", "Swedish (Finland)", "svenska (Finland)", "SVF", "swe", "sv", {0, 0, 0, 0, 0}, 58, 58}, - {0x0C01, 0x0001, 0x0C01, "ar-EG", "Arabic (Egypt)", "Arabic (Egypt)", "Arabic (Egypt)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x85\xd8\xb5\xd8\xb1)", "ARE", "ara", "ar", {16777216, 0, 0, 0, 0}, 59, 59}, - {0x0C07, 0x0007, 0x0C07, "de-AT", "German (Austria)", "German (Austria)", "German (Austria)", "Deutsch (\xc3\x96sterreich)", "DEA", "deu", "de", {0, 0, 0, 0, 0}, 60, 60}, - {0x0C09, 0x0009, 0x0C09, "en-AU", "English (Australia)", "English (Australia)", "English (Australia)", "English (Australia)", "ENA", "eng", "en", {0, 0, 0, 0, 0}, 61, 61}, - {0x0C0A, 0x000A, 0x0C0A, "es-ES", "Spanish (Spain)", "Spanish (Spain)", "Spanish (Spain)", "espa\xc3\xb1ol (Espa\xc3\xb1\x61)", "ESN", "spa", "es", {0, 0, 0, 0, 0}, 62, 62}, - {0x0C0C, 0x000C, 0x0C0C, "fr-CA", "French (Canada)", "French (Canada)", "French (Canada)", "fran\xc3\xa7\x61is (Canada)", "FRC", "fra", "fr", {0, 0, 0, 0, 0}, 63, 63}, - {0x1001, 0x0001, 0x1001, "ar-LY", "Arabic (Libya)", "Arabic (Libya)", "Arabic (Libya)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd9\x8a\xd8\xa8\xd9\x8a\xd8\xa7)", "ARL", "ara", "ar", {16777216, 0, 0, 0, 0}, 64, 64}, - {0x1007, 0x0007, 0x1007, "de-LU", "German (Luxembourg)", "German (Luxembourg)", "German (Luxembourg)", "Deutsch (Luxemburg)", "DEL", "deu", "de", {0, 0, 0, 0, 0}, 65, 65}, - {0x1009, 0x0009, 0x1009, "en-CA", "English (Canada)", "English (Canada)", "English (Canada)", "English (Canada)", "ENC", "eng", "en", {0, 0, 0, 0, 0}, 66, 66}, - {0x100A, 0x000A, 0x100A, "es-GT", "Spanish (Guatemala)", "Spanish (Guatemala)", "Spanish (Guatemala)", "espa\xc3\xb1ol (Guatemala)", "ESG", "spa", "es", {0, 0, 0, 0, 0}, 67, 67}, - {0x100C, 0x000C, 0x100C, "fr-CH", "French (Switzerland)", "French (Switzerland)", "French (Switzerland)", "fran\xc3\xa7\x61is (Suisse)", "FRS", "fra", "fr", {0, 0, 0, 0, 0}, 68, 68}, - {0x1401, 0x0001, 0x1401, "ar-DZ", "Arabic (Algeria)", "Arabic (Algeria)", "Arabic (Algeria)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1)", "ARG", "ara", "ar", {16777216, 0, 0, 0, 0}, 69, 69}, - {0x1409, 0x0009, 0x1409, "en-NZ", "English (New Zealand)", "English (New Zealand)", "English (New Zealand)", "English (New Zealand)", "ENZ", "eng", "en", {0, 0, 0, 0, 0}, 70, 70}, - {0x140A, 0x000A, 0x140A, "es-CR", "Spanish (Costa Rica)", "Spanish (Costa Rica)", "Spanish (Costa Rica)", "espa\xc3\xb1ol (Costa Rica)", "ESC", "spa", "es", {0, 0, 0, 0, 0}, 71, 71}, - {0x140C, 0x000C, 0x140C, "fr-LU", "French (Luxembourg)", "French (Luxembourg)", "French (Luxembourg)", "fran\xc3\xa7\x61is (Luxembourg)", "FRL", "fra", "fr", {0, 0, 0, 0, 0}, 72, 72}, - {0x1801, 0x0001, 0x1801, "ar-MA", "Arabic (Morocco)", "Arabic (Morocco)", "Arabic (Morocco)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8)", "ARM", "ara", "ar", {16777216, 0, 0, 0, 0}, 73, 73}, - {0x1809, 0x0009, 0x1809, "en-IE", "English (Ireland)", "English (Ireland)", "English (Ireland)", "English (Ireland)", "ENI", "eng", "en", {0, 0, 0, 0, 0}, 74, 74}, - {0x180A, 0x000A, 0x180A, "es-PA", "Spanish (Panama)", "Spanish (Panama)", "Spanish (Panama)", "espa\xc3\xb1ol (Panam\xc3\xa1)", "ESA", "spa", "es", {0, 0, 0, 0, 0}, 75, 75}, - {0x1C01, 0x0001, 0x1C01, "ar-TN", "Arabic (Tunisia)", "Arabic (Tunisia)", "Arabic (Tunisia)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3)", "ART", "ara", "ar", {16777216, 0, 0, 0, 0}, 76, 76}, - {0x1C09, 0x0009, 0x1C09, "en-ZA", "English (South Africa)", "English (South Africa)", "English (South Africa)", "English (South Africa)", "ENS", "eng", "en", {0, 0, 0, 0, 0}, 77, 77}, - {0x1C0A, 0x000A, 0x1C0A, "es-DO", "Spanish (Dominican Republic)", "Spanish (Dominican Republic)", "Spanish (Dominican Republic)", "espa\xc3\xb1ol (Rep\xc3\xba\x62lica Dominicana)", "ESD", "spa", "es", {0, 0, 0, 0, 0}, 78, 78}, - {0x2001, 0x0001, 0x2001, "ar-OM", "Arabic (Oman)", "Arabic (Oman)", "Arabic (Oman)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb9\xd9\x85\xd8\xa7\xd9\x86)", "ARO", "ara", "ar", {16777216, 0, 0, 0, 0}, 79, 79}, - {0x200A, 0x000A, 0x200A, "es-VE", "Spanish (Venezuela)", "Spanish (Venezuela)", "Spanish (Venezuela)", "espa\xc3\xb1ol (Venezuela)", "ESV", "spa", "es", {0, 0, 0, 0, 0}, 80, 80}, - {0x2401, 0x0001, 0x2401, "ar-YE", "Arabic (Yemen)", "Arabic (Yemen)", "Arabic (Yemen)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86)", "ARY", "ara", "ar", {16777216, 0, 0, 0, 0}, 81, 81}, - {0x240A, 0x000A, 0x240A, "es-CO", "Spanish (Colombia)", "Spanish (Colombia)", "Spanish (Colombia)", "espa\xc3\xb1ol (Colombia)", "ESO", "spa", "es", {0, 0, 0, 0, 0}, 82, 82}, - {0x2801, 0x0001, 0x2801, "ar-SY", "Arabic (Syria)", "Arabic (Syria)", "Arabic (Syria)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9)", "ARS", "ara", "ar", {16777216, 0, 0, 0, 0}, 83, 83}, - {0x280A, 0x000A, 0x280A, "es-PE", "Spanish (Peru)", "Spanish (Peru)", "Spanish (Peru)", "espa\xc3\xb1ol (Per\xc3\xba)", "ESR", "spa", "es", {0, 0, 0, 0, 0}, 84, 84}, - {0x2C01, 0x0001, 0x2C01, "ar-JO", "Arabic (Jordan)", "Arabic (Jordan)", "Arabic (Jordan)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x86)", "ARJ", "ara", "ar", {16777216, 0, 0, 0, 0}, 85, 85}, - {0x2C0A, 0x000A, 0x2C0A, "es-AR", "Spanish (Argentina)", "Spanish (Argentina)", "Spanish (Argentina)", "espa\xc3\xb1ol (Argentina)", "ESS", "spa", "es", {0, 0, 0, 0, 0}, 86, 86}, - {0x3001, 0x0001, 0x3001, "ar-LB", "Arabic (Lebanon)", "Arabic (Lebanon)", "Arabic (Lebanon)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd8\xa8\xd9\x86\xd8\xa7\xd9\x86)", "ARB", "ara", "ar", {16777216, 0, 0, 0, 0}, 87, 87}, - {0x3009, 0x0009, 0x3009, "en-ZW", "English (Zimbabwe)", "English (Zimbabwe)", "English (Zimbabwe)", "English (Zimbabwe)", "ENW", "eng", "en", {0, 0, 0, 0, 0}, 88, 88}, - {0x300A, 0x000A, 0x300A, "es-EC", "Spanish (Ecuador)", "Spanish (Ecuador)", "Spanish (Ecuador)", "espa\xc3\xb1ol (Ecuador)", "ESF", "spa", "es", {0, 0, 0, 0, 0}, 89, 89}, - {0x3401, 0x0001, 0x3401, "ar-KW", "Arabic (Kuwait)", "Arabic (Kuwait)", "Arabic (Kuwait)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x83\xd9\x88\xd9\x8a\xd8\xaa)", "ARK", "ara", "ar", {16777216, 0, 0, 0, 0}, 90, 90}, - {0x3409, 0x0009, 0x3409, "en-PH", "English (Philippines)", "English (Philippines)", "English (Philippines)", "English (Philippines)", "ENP", "eng", "en", {0, 0, 0, 0, 0}, 91, 91}, - {0x340A, 0x000A, 0x340A, "es-CL", "Spanish (Chile)", "Spanish (Chile)", "Spanish (Chile)", "espa\xc3\xb1ol (Chile)", "ESL", "spa", "es", {0, 0, 0, 0, 0}, 92, 92}, - {0x3801, 0x0001, 0x3801, "ar-AE", "Arabic (United Arab Emirates)", "Arabic (United Arab Emirates)", "Arabic (United Arab Emirates)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa7\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd9\x85\xd8\xaa\xd8\xad\xd8\xaf\xd8\xa9)", "ARU", "ara", "ar", {16777216, 0, 0, 0, 0}, 93, 93}, - {0x380A, 0x000A, 0x380A, "es-UY", "Spanish (Uruguay)", "Spanish (Uruguay)", "Spanish (Uruguay)", "espa\xc3\xb1ol (Uruguay)", "ESY", "spa", "es", {0, 0, 0, 0, 0}, 94, 94}, - {0x3C01, 0x0001, 0x3C01, "ar-BH", "Arabic (Bahrain)", "Arabic (Bahrain)", "Arabic (Bahrain)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86)", "ARH", "ara", "ar", {16777216, 0, 0, 0, 0}, 95, 95}, - {0x3C0A, 0x000A, 0x3C0A, "es-PY", "Spanish (Paraguay)", "Spanish (Paraguay)", "Spanish (Paraguay)", "espa\xc3\xb1ol (Paraguay)", "ESZ", "spa", "es", {0, 0, 0, 0, 0}, 96, 96}, - {0x4001, 0x0001, 0x4001, "ar-QA", "Arabic (Qatar)", "Arabic (Qatar)", "Arabic (Qatar)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x82\xd8\xb7\xd8\xb1)", "ARQ", "ara", "ar", {16777216, 0, 0, 0, 0}, 97, 97}, - {0x400A, 0x000A, 0x400A, "es-BO", "Spanish (Bolivia)", "Spanish (Bolivia)", "Spanish (Bolivia)", "espa\xc3\xb1ol (Bolivia)", "ESB", "spa", "es", {0, 0, 0, 0, 0}, 98, 98}, - {0x440A, 0x000A, 0x440A, "es-SV", "Spanish (El Salvador)", "Spanish (El Salvador)", "Spanish (El Salvador)", "espa\xc3\xb1ol (El Salvador)", "ESE", "spa", "es", {0, 0, 0, 0, 0}, 99, 99}, - {0x480A, 0x000A, 0x480A, "es-HN", "Spanish (Honduras)", "Spanish (Honduras)", "Spanish (Honduras)", "espa\xc3\xb1ol (Honduras)", "ESH", "spa", "es", {0, 0, 0, 0, 0}, 100, 100}, - {0x4C0A, 0x000A, 0x4C0A, "es-NI", "Spanish (Nicaragua)", "Spanish (Nicaragua)", "Spanish (Nicaragua)", "espa\xc3\xb1ol (Nicaragua)", "ESI", "spa", "es", {0, 0, 0, 0, 0}, 101, 101}, - {0x500A, 0x000A, 0x500A, "es-PR", "Spanish (Puerto Rico)", "Spanish (Puerto Rico)", "Spanish (Puerto Rico)", "espa\xc3\xb1ol (Puerto Rico)", "ESU", "spa", "es", {0, 0, 0, 0, 0}, 102, 102} + {0x042B, 0x002B, 0x042B, "hy-AM", "Armenian (Armenia)", "Armenian (Armenia)", "Armenian (Armenia)", "\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa7\xd5\xb6 (\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa1\xd5\xbd\xd5\xbf\xd5\xa1\xd5\xb6\xd5\xab \xd5\x80\xd5\xa1\xd5\xb6\xd6\x80\xd5\xa1\xd5\xba\xd5\xa5\xd5\xbf\xd5\xb8\xd6\x82\xd5\xa9\xd5\xab\xd6\x82\xd5\xb6)", "HYE", "hye", "hy", {0, 0, 0, 0, 0}, 37, 37}, + {0x042D, 0x002D, 0x042D, "eu-ES", "Basque (Spain)", "Basque (Spain)", "Basque (Spain)", "euskara (Espainia)", "EUQ", "eus", "eu", {0, 0, 0, 0, 0}, 38, 38}, + {0x042F, 0x002F, 0x042F, "mk-MK", "Macedonian (Macedonia)", "Macedonian (Macedonia)", "Macedonian (Macedonia)", "\xd0\xbc\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x9c\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd0\xb8\xd1\x98\xd0\xb0)", "MKI", "mkd", "mk", {0, 0, 0, 0, 0}, 39, 39}, + {0x0436, 0x0036, 0x0436, "af-ZA", "Afrikaans (South Africa)", "Afrikaans (South Africa)", "Afrikaans (South Africa)", "Afrikaanse (Suid-Afrika)", "AFK", "afr", "af", {0, 0, 0, 0, 0}, 40, 40}, + {0x0438, 0x0038, 0x0438, "fo-FO", "Faroese (Faroe Islands)", "Faroese (Faroe Islands)", "Faroese (Faroe Islands)", "f\xc3\xb8royskt (F\xc3\xb8royar)", "FOS", "fao", "fo", {0, 0, 0, 0, 0}, 41, 41}, + {0x0439, 0x0039, 0x0439, "hi-IN", "Hindi (India)", "Hindi (India)", "Hindi (India)", "\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)", "HIN", "hin", "hi", {0, 0, 0, 0, 0}, 42, 42}, + {0x0441, 0x0041, 0x0441, "sw-KE", "Swahili (Kenya)", "Swahili (Kenya)", "Swahili (Kenya)", "Kiswahili (Kenya)", "SWK", "swa", "sw", {0, 0, 0, 0, 0}, 43, 43}, + {0x0447, 0x0047, 0x0447, "gu-IN", "Gujarati (India)", "Gujarati (India)", "Gujarati (India)", "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\x9c\xe0\xaa\xb0\xe0\xaa\xbe\xe0\xaa\xa4\xe0\xab\x80 (\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4)", "GUJ", "guj", "gu", {0, 0, 0, 0, 0}, 44, 44}, + {0x0449, 0x0049, 0x0449, "ta-IN", "Tamil (India)", "Tamil (India)", "Tamil (India)", "\xe0\xae\xa4\xe0\xae\xae\xe0\xae\xbf\xe0\xae\xb4\xe0\xaf\x8d (\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe)", "TAM", "tam", "ta", {0, 0, 0, 0, 0}, 45, 45}, + {0x044A, 0x004A, 0x044A, "te-IN", "Telugu (India)", "Telugu (India)", "Telugu (India)", "\xe0\xb0\xa4\xe0\xb1\x86\xe0\xb0\xb2\xe0\xb1\x81\xe0\xb0\x97\xe0\xb1\x81 (\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4 \xe0\xb0\xa6\xe0\xb1\x87\xe0\xb0\xb3\xe0\xb1\xa6)", "TEL", "tel", "te", {0, 0, 0, 0, 0}, 46, 46}, + {0x044B, 0x004B, 0x044B, "kn-IN", "Kannada (India)", "Kannada (India)", "Kannada (India)", "\xe0\xb2\x95\xe0\xb2\xa8\xe0\xb3\x8d\xe0\xb2\xa8\xe0\xb2\xa1 (\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4)", "KAN", "kan", "kn", {0, 0, 0, 0, 0}, 47, 47}, + {0x044E, 0x004E, 0x044E, "mr-IN", "Marathi (India)", "Marathi (India)", "Marathi (India)", "\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)", "MAR", "mar", "mr", {0, 0, 0, 0, 0}, 48, 48}, + {0x0456, 0x0056, 0x0456, "gl-ES", "Gallegan (Spain)", "Gallegan (Spain)", "Gallegan (Spain)", "galego (Espa\xc3\xb1\x61)", "GLC", "glg", "gl", {0, 0, 0, 0, 0}, 49, 49}, + {0x0457, 0x0057, 0x0457, "kok-IN", "Konkani (India)", "Konkani (India)", "Konkani (India)", "\xe0\xa4\x95\xe0\xa5\x8b\xe0\xa4\x82\xe0\xa4\x95\xe0\xa4\xa3\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)", "KNK", "kok", "kok", {0, 0, 0, 0, 0}, 50, 50}, + {0x0801, 0x0001, 0x0801, "ar-IQ", "Arabic (Iraq)", "Arabic (Iraq)", "Arabic (Iraq)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82)", "ARI", "ara", "ar", {2, 1, 0, 0, 0}, 51, 51}, + {0x0807, 0x0007, 0x0807, "de-CH", "German (Switzerland)", "German (Switzerland)", "German (Switzerland)", "Deutsch (Schweiz)", "DES", "deu", "de", {0, 0, 0, 0, 0}, 52, 52}, + {0x0809, 0x0009, 0x0809, "en-GB", "English (United Kingdom)", "English (United Kingdom)", "English (United Kingdom)", "English (United Kingdom)", "ENG", "eng", "en", {0, 0, 0, 0, 0}, 53, 53}, + {0x080A, 0x000A, 0x080A, "es-MX", "Spanish (Mexico)", "Spanish (Mexico)", "Spanish (Mexico)", "espa\xc3\xb1ol (M\xc3\xa9xico)", "ESM", "spa", "es", {0, 0, 0, 0, 0}, 54, 54}, + {0x080C, 0x000C, 0x080C, "fr-BE", "French (Belgium)", "French (Belgium)", "French (Belgium)", "fran\xc3\xa7\x61is (Belgique)", "FRB", "fra", "fr", {0, 0, 0, 0, 0}, 55, 55}, + {0x0810, 0x0010, 0x0810, "it-CH", "Italian (Switzerland)", "Italian (Switzerland)", "Italian (Switzerland)", "italiano (Svizzera)", "ITS", "ita", "it", {0, 0, 0, 0, 0}, 56, 56}, + {0x0813, 0x0013, 0x0813, "nl-BE", "Dutch (Belgium)", "Dutch (Belgium)", "Dutch (Belgium)", "Nederlands (Belgi\xc3\xab)", "NLB", "nld", "nl", {0, 0, 0, 0, 0}, 57, 57}, + {0x0816, 0x0016, 0x0816, "pt-PT", "Portuguese (Portugal)", "Portuguese (Portugal)", "Portuguese (Portugal)", "portugu\xc3\xaas (Portugal)", "PTG", "por", "pt", {0, 0, 0, 0, 0}, 58, 58}, + {0x081D, 0x001D, 0x081D, "sv-FI", "Swedish (Finland)", "Swedish (Finland)", "Swedish (Finland)", "svenska (Finland)", "SVF", "swe", "sv", {0, 0, 0, 0, 0}, 59, 59}, + {0x0C01, 0x0001, 0x0C01, "ar-EG", "Arabic (Egypt)", "Arabic (Egypt)", "Arabic (Egypt)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x85\xd8\xb5\xd8\xb1)", "ARE", "ara", "ar", {16777216, 0, 0, 0, 0}, 60, 60}, + {0x0C07, 0x0007, 0x0C07, "de-AT", "German (Austria)", "German (Austria)", "German (Austria)", "Deutsch (\xc3\x96sterreich)", "DEA", "deu", "de", {0, 0, 0, 0, 0}, 61, 61}, + {0x0C09, 0x0009, 0x0C09, "en-AU", "English (Australia)", "English (Australia)", "English (Australia)", "English (Australia)", "ENA", "eng", "en", {0, 0, 0, 0, 0}, 62, 62}, + {0x0C0A, 0x000A, 0x0C0A, "es-ES", "Spanish (Spain)", "Spanish (Spain)", "Spanish (Spain)", "espa\xc3\xb1ol (Espa\xc3\xb1\x61)", "ESN", "spa", "es", {0, 0, 0, 0, 0}, 63, 63}, + {0x0C0C, 0x000C, 0x0C0C, "fr-CA", "French (Canada)", "French (Canada)", "French (Canada)", "fran\xc3\xa7\x61is (Canada)", "FRC", "fra", "fr", {0, 0, 0, 0, 0}, 64, 64}, + {0x1001, 0x0001, 0x1001, "ar-LY", "Arabic (Libya)", "Arabic (Libya)", "Arabic (Libya)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd9\x8a\xd8\xa8\xd9\x8a\xd8\xa7)", "ARL", "ara", "ar", {16777216, 0, 0, 0, 0}, 65, 65}, + {0x1007, 0x0007, 0x1007, "de-LU", "German (Luxembourg)", "German (Luxembourg)", "German (Luxembourg)", "Deutsch (Luxemburg)", "DEL", "deu", "de", {0, 0, 0, 0, 0}, 66, 66}, + {0x1009, 0x0009, 0x1009, "en-CA", "English (Canada)", "English (Canada)", "English (Canada)", "English (Canada)", "ENC", "eng", "en", {0, 0, 0, 0, 0}, 67, 67}, + {0x100A, 0x000A, 0x100A, "es-GT", "Spanish (Guatemala)", "Spanish (Guatemala)", "Spanish (Guatemala)", "espa\xc3\xb1ol (Guatemala)", "ESG", "spa", "es", {0, 0, 0, 0, 0}, 68, 68}, + {0x100C, 0x000C, 0x100C, "fr-CH", "French (Switzerland)", "French (Switzerland)", "French (Switzerland)", "fran\xc3\xa7\x61is (Suisse)", "FRS", "fra", "fr", {0, 0, 0, 0, 0}, 69, 69}, + {0x1401, 0x0001, 0x1401, "ar-DZ", "Arabic (Algeria)", "Arabic (Algeria)", "Arabic (Algeria)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1)", "ARG", "ara", "ar", {16777216, 0, 0, 0, 0}, 70, 70}, + {0x1409, 0x0009, 0x1409, "en-NZ", "English (New Zealand)", "English (New Zealand)", "English (New Zealand)", "English (New Zealand)", "ENZ", "eng", "en", {0, 0, 0, 0, 0}, 71, 71}, + {0x140A, 0x000A, 0x140A, "es-CR", "Spanish (Costa Rica)", "Spanish (Costa Rica)", "Spanish (Costa Rica)", "espa\xc3\xb1ol (Costa Rica)", "ESC", "spa", "es", {0, 0, 0, 0, 0}, 72, 72}, + {0x140C, 0x000C, 0x140C, "fr-LU", "French (Luxembourg)", "French (Luxembourg)", "French (Luxembourg)", "fran\xc3\xa7\x61is (Luxembourg)", "FRL", "fra", "fr", {0, 0, 0, 0, 0}, 73, 73}, + {0x1801, 0x0001, 0x1801, "ar-MA", "Arabic (Morocco)", "Arabic (Morocco)", "Arabic (Morocco)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8)", "ARM", "ara", "ar", {16777216, 0, 0, 0, 0}, 74, 74}, + {0x1809, 0x0009, 0x1809, "en-IE", "English (Ireland)", "English (Ireland)", "English (Ireland)", "English (Ireland)", "ENI", "eng", "en", {0, 0, 0, 0, 0}, 75, 75}, + {0x180A, 0x000A, 0x180A, "es-PA", "Spanish (Panama)", "Spanish (Panama)", "Spanish (Panama)", "espa\xc3\xb1ol (Panam\xc3\xa1)", "ESA", "spa", "es", {0, 0, 0, 0, 0}, 76, 76}, + {0x1C01, 0x0001, 0x1C01, "ar-TN", "Arabic (Tunisia)", "Arabic (Tunisia)", "Arabic (Tunisia)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3)", "ART", "ara", "ar", {16777216, 0, 0, 0, 0}, 77, 77}, + {0x1C09, 0x0009, 0x1C09, "en-ZA", "English (South Africa)", "English (South Africa)", "English (South Africa)", "English (South Africa)", "ENS", "eng", "en", {0, 0, 0, 0, 0}, 78, 78}, + {0x1C0A, 0x000A, 0x1C0A, "es-DO", "Spanish (Dominican Republic)", "Spanish (Dominican Republic)", "Spanish (Dominican Republic)", "espa\xc3\xb1ol (Rep\xc3\xba\x62lica Dominicana)", "ESD", "spa", "es", {0, 0, 0, 0, 0}, 79, 79}, + {0x2001, 0x0001, 0x2001, "ar-OM", "Arabic (Oman)", "Arabic (Oman)", "Arabic (Oman)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb9\xd9\x85\xd8\xa7\xd9\x86)", "ARO", "ara", "ar", {16777216, 0, 0, 0, 0}, 80, 80}, + {0x200A, 0x000A, 0x200A, "es-VE", "Spanish (Venezuela)", "Spanish (Venezuela)", "Spanish (Venezuela)", "espa\xc3\xb1ol (Venezuela)", "ESV", "spa", "es", {0, 0, 0, 0, 0}, 81, 81}, + {0x2401, 0x0001, 0x2401, "ar-YE", "Arabic (Yemen)", "Arabic (Yemen)", "Arabic (Yemen)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86)", "ARY", "ara", "ar", {16777216, 0, 0, 0, 0}, 82, 82}, + {0x240A, 0x000A, 0x240A, "es-CO", "Spanish (Colombia)", "Spanish (Colombia)", "Spanish (Colombia)", "espa\xc3\xb1ol (Colombia)", "ESO", "spa", "es", {0, 0, 0, 0, 0}, 83, 83}, + {0x2801, 0x0001, 0x2801, "ar-SY", "Arabic (Syria)", "Arabic (Syria)", "Arabic (Syria)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9)", "ARS", "ara", "ar", {16777216, 0, 0, 0, 0}, 84, 84}, + {0x280A, 0x000A, 0x280A, "es-PE", "Spanish (Peru)", "Spanish (Peru)", "Spanish (Peru)", "espa\xc3\xb1ol (Per\xc3\xba)", "ESR", "spa", "es", {0, 0, 0, 0, 0}, 85, 85}, + {0x2C01, 0x0001, 0x2C01, "ar-JO", "Arabic (Jordan)", "Arabic (Jordan)", "Arabic (Jordan)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x86)", "ARJ", "ara", "ar", {16777216, 0, 0, 0, 0}, 86, 86}, + {0x2C0A, 0x000A, 0x2C0A, "es-AR", "Spanish (Argentina)", "Spanish (Argentina)", "Spanish (Argentina)", "espa\xc3\xb1ol (Argentina)", "ESS", "spa", "es", {0, 0, 0, 0, 0}, 87, 87}, + {0x3001, 0x0001, 0x3001, "ar-LB", "Arabic (Lebanon)", "Arabic (Lebanon)", "Arabic (Lebanon)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd8\xa8\xd9\x86\xd8\xa7\xd9\x86)", "ARB", "ara", "ar", {16777216, 0, 0, 0, 0}, 88, 88}, + {0x3009, 0x0009, 0x3009, "en-ZW", "English (Zimbabwe)", "English (Zimbabwe)", "English (Zimbabwe)", "English (Zimbabwe)", "ENW", "eng", "en", {0, 0, 0, 0, 0}, 89, 89}, + {0x300A, 0x000A, 0x300A, "es-EC", "Spanish (Ecuador)", "Spanish (Ecuador)", "Spanish (Ecuador)", "espa\xc3\xb1ol (Ecuador)", "ESF", "spa", "es", {0, 0, 0, 0, 0}, 90, 90}, + {0x3401, 0x0001, 0x3401, "ar-KW", "Arabic (Kuwait)", "Arabic (Kuwait)", "Arabic (Kuwait)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x83\xd9\x88\xd9\x8a\xd8\xaa)", "ARK", "ara", "ar", {16777216, 0, 0, 0, 0}, 91, 91}, + {0x3409, 0x0009, 0x3409, "en-PH", "English (Philippines)", "English (Philippines)", "English (Philippines)", "English (Philippines)", "ENP", "eng", "en", {0, 0, 0, 0, 0}, 92, 92}, + {0x340A, 0x000A, 0x340A, "es-CL", "Spanish (Chile)", "Spanish (Chile)", "Spanish (Chile)", "espa\xc3\xb1ol (Chile)", "ESL", "spa", "es", {0, 0, 0, 0, 0}, 93, 93}, + {0x3801, 0x0001, 0x3801, "ar-AE", "Arabic (United Arab Emirates)", "Arabic (United Arab Emirates)", "Arabic (United Arab Emirates)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa7\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd9\x85\xd8\xaa\xd8\xad\xd8\xaf\xd8\xa9)", "ARU", "ara", "ar", {16777216, 0, 0, 0, 0}, 94, 94}, + {0x380A, 0x000A, 0x380A, "es-UY", "Spanish (Uruguay)", "Spanish (Uruguay)", "Spanish (Uruguay)", "espa\xc3\xb1ol (Uruguay)", "ESY", "spa", "es", {0, 0, 0, 0, 0}, 95, 95}, + {0x3C01, 0x0001, 0x3C01, "ar-BH", "Arabic (Bahrain)", "Arabic (Bahrain)", "Arabic (Bahrain)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86)", "ARH", "ara", "ar", {16777216, 0, 0, 0, 0}, 96, 96}, + {0x3C0A, 0x000A, 0x3C0A, "es-PY", "Spanish (Paraguay)", "Spanish (Paraguay)", "Spanish (Paraguay)", "espa\xc3\xb1ol (Paraguay)", "ESZ", "spa", "es", {0, 0, 0, 0, 0}, 97, 97}, + {0x4001, 0x0001, 0x4001, "ar-QA", "Arabic (Qatar)", "Arabic (Qatar)", "Arabic (Qatar)", "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x82\xd8\xb7\xd8\xb1)", "ARQ", "ara", "ar", {16777216, 0, 0, 0, 0}, 98, 98}, + {0x400A, 0x000A, 0x400A, "es-BO", "Spanish (Bolivia)", "Spanish (Bolivia)", "Spanish (Bolivia)", "espa\xc3\xb1ol (Bolivia)", "ESB", "spa", "es", {0, 0, 0, 0, 0}, 99, 99}, + {0x440A, 0x000A, 0x440A, "es-SV", "Spanish (El Salvador)", "Spanish (El Salvador)", "Spanish (El Salvador)", "espa\xc3\xb1ol (El Salvador)", "ESE", "spa", "es", {0, 0, 0, 0, 0}, 100, 100}, + {0x480A, 0x000A, 0x480A, "es-HN", "Spanish (Honduras)", "Spanish (Honduras)", "Spanish (Honduras)", "espa\xc3\xb1ol (Honduras)", "ESH", "spa", "es", {0, 0, 0, 0, 0}, 101, 101}, + {0x4C0A, 0x000A, 0x4C0A, "es-NI", "Spanish (Nicaragua)", "Spanish (Nicaragua)", "Spanish (Nicaragua)", "espa\xc3\xb1ol (Nicaragua)", "ESI", "spa", "es", {0, 0, 0, 0, 0}, 102, 102}, + {0x500A, 0x000A, 0x500A, "es-PR", "Spanish (Puerto Rico)", "Spanish (Puerto Rico)", "Spanish (Puerto Rico)", "espa\xc3\xb1ol (Puerto Rico)", "ESU", "spa", "es", {0, 0, 0, 0, 0}, 103, 103} }; -
-static const CultureInfoNameEntry culture_name_entries [] = {
+ +static const CultureInfoNameEntry culture_name_entries [] = { {"af", 40}, - {"af-za", 90}, + {"af-za", 91}, {"ar", 0}, - {"ar-ae", 144}, - {"ar-bh", 146}, - {"ar-dz", 120}, - {"ar-eg", 110}, - {"ar-iq", 101}, - {"ar-jo", 136}, - {"ar-kw", 141}, - {"ar-lb", 138}, - {"ar-ly", 115}, - {"ar-ma", 124}, - {"ar-om", 130}, - {"ar-qa", 148}, - {"ar-sy", 134}, - {"ar-tn", 127}, - {"ar-ye", 132}, + {"ar-ae", 145}, + {"ar-bh", 147}, + {"ar-dz", 121}, + {"ar-eg", 111}, + {"ar-iq", 102}, + {"ar-jo", 137}, + {"ar-kw", 142}, + {"ar-lb", 139}, + {"ar-ly", 116}, + {"ar-ma", 125}, + {"ar-om", 131}, + {"ar-qa", 149}, + {"ar-sa", 51}, + {"ar-sy", 135}, + {"ar-tn", 128}, + {"ar-ye", 133}, {"be", 30}, - {"be-by", 79}, + {"be-by", 80}, {"bg", 1}, - {"bg-bg", 51}, + {"bg-bg", 52}, {"ca", 2}, - {"ca-es", 52}, + {"ca-es", 53}, {"cs", 3}, - {"cs-cz", 53}, + {"cs-cz", 54}, {"da", 4}, - {"da-dk", 54}, + {"da-dk", 55}, {"de", 5}, - {"de-at", 111}, - {"de-ch", 102}, - {"de-de", 55}, - {"de-lu", 116}, + {"de-at", 112}, + {"de-ch", 103}, + {"de-de", 56}, + {"de-lu", 117}, {"el", 6}, - {"el-gr", 56}, + {"el-gr", 57}, {"en", 7}, - {"en-au", 112}, - {"en-ca", 117}, - {"en-gb", 103}, - {"en-ie", 125}, - {"en-nz", 121}, - {"en-ph", 142}, - {"en-us", 57}, - {"en-za", 128}, - {"en-zw", 139}, + {"en-au", 113}, + {"en-ca", 118}, + {"en-gb", 104}, + {"en-ie", 126}, + {"en-nz", 122}, + {"en-ph", 143}, + {"en-us", 58}, + {"en-za", 129}, + {"en-zw", 140}, {"es", 8}, - {"es-ar", 137}, - {"es-bo", 149}, - {"es-cl", 143}, - {"es-co", 133}, - {"es-cr", 122}, - {"es-do", 129}, - {"es-ec", 140}, - {"es-es", 113}, - {"es-gt", 118}, - {"es-hn", 151}, - {"es-mx", 104}, - {"es-ni", 152}, - {"es-pa", 126}, - {"es-pe", 135}, - {"es-pr", 153}, - {"es-py", 147}, - {"es-sv", 150}, - {"es-uy", 145}, - {"es-ve", 131}, + {"es-ar", 138}, + {"es-bo", 150}, + {"es-cl", 144}, + {"es-co", 134}, + {"es-cr", 123}, + {"es-do", 130}, + {"es-ec", 141}, + {"es-es", 114}, + {"es-gt", 119}, + {"es-hn", 152}, + {"es-mx", 105}, + {"es-ni", 153}, + {"es-pa", 127}, + {"es-pe", 136}, + {"es-pr", 154}, + {"es-py", 148}, + {"es-sv", 151}, + {"es-uy", 146}, + {"es-ve", 132}, {"et", 32}, - {"et-ee", 81}, + {"et-ee", 82}, {"eu", 38}, - {"eu-es", 88}, + {"eu-es", 89}, {"fa", 35}, - {"fa-ir", 84}, + {"fa-ir", 85}, {"fi", 9}, - {"fi-fi", 58}, + {"fi-fi", 59}, {"fo", 41}, - {"fo-fo", 91}, + {"fo-fo", 92}, {"fr", 10}, - {"fr-be", 105}, - {"fr-ca", 114}, - {"fr-ch", 119}, - {"fr-fr", 59}, - {"fr-lu", 123}, + {"fr-be", 106}, + {"fr-ca", 115}, + {"fr-ch", 120}, + {"fr-fr", 60}, + {"fr-lu", 124}, {"gl", 49}, - {"gl-es", 99}, + {"gl-es", 100}, {"gu", 44}, - {"gu-in", 94}, + {"gu-in", 95}, {"he", 11}, - {"he-il", 60}, + {"he-il", 61}, {"hi", 42}, - {"hi-in", 92}, + {"hi-in", 93}, {"hr", 22}, - {"hr-hr", 71}, + {"hr-hr", 72}, {"hu", 12}, - {"hu-hu", 61}, + {"hu-hu", 62}, {"hy", 37}, - {"hy-am", 86}, {"hy-am", 87}, + {"hy-am", 88}, {"id", 28}, - {"id-id", 77}, + {"id-id", 78}, {"is", 13}, - {"is-is", 62}, + {"is-is", 63}, {"it", 14}, - {"it-ch", 106}, - {"it-it", 63}, + {"it-ch", 107}, + {"it-it", 64}, {"ja", 15}, - {"ja-jp", 64}, + {"ja-jp", 65}, {"kn", 47}, - {"kn-in", 97}, + {"kn-in", 98}, {"ko", 16}, + {"ko-kr", 66}, {"kok", 50}, - {"kok-in", 100}, - {"ko-kr", 65}, + {"kok-in", 101}, {"lt", 34}, - {"lt-lt", 83}, + {"lt-lt", 84}, {"lv", 33}, - {"lv-lv", 82}, + {"lv-lv", 83}, {"mk", 39}, - {"mk-mk", 89}, + {"mk-mk", 90}, {"mr", 48}, - {"mr-in", 98}, + {"mr-in", 99}, {"nl", 17}, - {"nl-be", 107}, - {"nl-nl", 66}, + {"nl-be", 108}, + {"nl-nl", 67}, {"pl", 18}, - {"pl-pl", 67}, + {"pl-pl", 68}, {"pt", 19}, - {"pt-br", 68}, - {"pt-pt", 108}, + {"pt-br", 69}, + {"pt-pt", 109}, {"ro", 20}, - {"ro-ro", 69}, + {"ro-ro", 70}, {"ru", 21}, - {"ru-ru", 70}, + {"ru-ru", 71}, {"sk", 23}, - {"sk-sk", 72}, + {"sk-sk", 73}, {"sl", 31}, - {"sl-si", 80}, + {"sl-si", 81}, {"sq", 24}, - {"sq-al", 73}, + {"sq-al", 74}, {"sv", 25}, - {"sv-fi", 109}, - {"sv-se", 74}, + {"sv-fi", 110}, + {"sv-se", 75}, {"sw", 43}, - {"sw-ke", 93}, + {"sw-ke", 94}, {"ta", 45}, - {"ta-in", 95}, + {"ta-in", 96}, {"te", 46}, - {"te-in", 96}, + {"te-in", 97}, {"th", 26}, - {"th-th", 75}, + {"th-th", 76}, {"tr", 27}, - {"tr-tr", 76}, + {"tr-tr", 77}, {"uk", 29}, - {"uk-ua", 78}, + {"uk-ua", 79}, {"vi", 36}, - {"vi-vn", 85} + {"vi-vn", 86} }; -
+ #endif -
+ diff --git a/mono/metadata/debug-mono-symfile.c b/mono/metadata/debug-mono-symfile.c index 4f39e6827f1..a44c2748e18 100644 --- a/mono/metadata/debug-mono-symfile.c +++ b/mono/metadata/debug-mono-symfile.c @@ -107,17 +107,21 @@ mono_debug_open_mono_symbol_file (MonoDebugHandle *handle, gboolean create_symfi { MonoSymbolFile *symfile; + mono_loader_lock (); symfile = g_new0 (MonoSymbolFile, 1); symfile->raw_contents = open_symfile (handle->image, &symfile->raw_contents_size); - if (load_symfile (handle, symfile)) + if (load_symfile (handle, symfile)) { + mono_loader_unlock (); return symfile; - else if (!create_symfile) { + } else if (!create_symfile) { mono_debug_close_mono_symbol_file (symfile); + mono_loader_unlock (); return NULL; } + mono_loader_unlock (); return symfile; } @@ -127,16 +131,18 @@ mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile) if (!symfile) return; + mono_loader_lock (); if (symfile->method_hash) g_hash_table_destroy (symfile->method_hash); g_free (symfile); + mono_loader_unlock (); } static gchar * read_string (const char *ptr) { - int len = *((guint32 *) ptr); + int len = read32 (ptr); ptr += sizeof(guint32); return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL); } @@ -151,12 +157,17 @@ mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, gu const char *ptr; int i; - if (!symfile->method_hash) + mono_loader_lock (); + if (!symfile->method_hash) { + mono_loader_unlock (); return NULL; + } minfo = g_hash_table_lookup (symfile->method_hash, method); - if (!minfo) + if (!minfo) { + mono_loader_unlock (); return NULL; + } if (read32(&(minfo->entry->_source_index))) { int offset = read32(&(symfile->offset_table->_source_table_offset)) + @@ -176,6 +187,7 @@ mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, gu if (line_number) { *line_number = read32(&(lne->_row)); + mono_loader_unlock (); if (source_file) return source_file; else @@ -183,11 +195,16 @@ mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, gu } else if (source_file) { gchar *retval = g_strdup_printf ("%s:%d", source_file, read32(&(lne->_row))); g_free (source_file); + mono_loader_unlock (); return retval; - } else - return g_strdup_printf ("%d", read32(&(lne->_row))); + } else { + gchar* retval = g_strdup_printf ("%d", read32(&(lne->_row))); + mono_loader_unlock (); + return retval; + } } + mono_loader_unlock (); return NULL; } @@ -233,6 +250,7 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method) if (handle->image != mono_class_get_image (mono_method_get_class (method))) return NULL; + mono_loader_lock (); first_ie = (MonoSymbolFileMethodIndexEntry *) (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset))); @@ -240,8 +258,10 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method) read32(&(symfile->offset_table->_method_count)), sizeof (MonoSymbolFileMethodIndexEntry), compare_method); - if (!ie) + if (!ie) { + mono_loader_unlock (); return NULL; + } me = (MonoSymbolFileMethodEntry *) (symfile->raw_contents + read32(&(ie->_file_offset))); @@ -256,5 +276,6 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method) g_hash_table_insert (symfile->method_hash, method, minfo); + mono_loader_unlock (); return minfo; } diff --git a/mono/metadata/filewatcher.c b/mono/metadata/filewatcher.c index 6210dc6b1f8..731eb3a1ad2 100644 --- a/mono/metadata/filewatcher.c +++ b/mono/metadata/filewatcher.c @@ -89,21 +89,26 @@ static int (*FAMNextEvent) (gpointer, gpointer); gint ves_icall_System_IO_FSW_SupportsFSW (void) { +#if HAVE_KQUEUE + return 3; +#else GModule *fam_module; + gchar *filename; MONO_ARCH_SAVE_REGS; - fam_module = g_module_open ("libfam", G_MODULE_BIND_LAZY); - if (fam_module == NULL) { + filename = g_module_build_path (NULL, "libfam.so.0"); + fam_module = g_module_open (filename, G_MODULE_BIND_LAZY); + g_free (filename); + if (fam_module == NULL) return 0; - } - g_module_symbol (fam_module, "FAMNextEvent", (gpointer *) &FAMNextEvent); if (FAMNextEvent == NULL) return 0; return 2; +#endif } gpointer diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 4695c8c1a2a..3a9db3a1c62 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -16,6 +16,7 @@ #include <mono/metadata/exception.h> #include <mono/metadata/domain-internals.h> #include <mono/metadata/class-internals.h> +#include <mono/utils/mono-logger.h> #define GC_I_HIDE_POINTERS #include <mono/os/gc_wrapper.h> @@ -347,13 +348,17 @@ ves_icall_System_GCHandle_GetTargetHandle (MonoObject *obj, guint32 handle, gint /* Indexes start from 1 since 0 means the handle is not allocated */ idx = ++next_handle; if (idx >= array_size) { -#if HAVE_BOEHM_GC gpointer *new_array; guint8 *new_type_array; if (!array_size) array_size = 16; +#if HAVE_BOEHM_GC new_array = GC_MALLOC (sizeof (gpointer) * (array_size * 2)); new_type_array = GC_MALLOC (sizeof (guint8) * (array_size * 2)); +#else + new_array = g_malloc0 (sizeof (gpointer) * (array_size * 2)); + new_type_array = g_malloc0 (sizeof (guint8) * (array_size * 2)); +#endif if (gc_handles) { int i; memcpy (new_array, gc_handles, sizeof (gpointer) * array_size); @@ -370,20 +375,22 @@ ves_icall_System_GCHandle_GetTargetHandle (MonoObject *obj, guint32 handle, gint #else if (((gulong)new_array [i]) & 0x1) { #endif +#if HAVE_BOEHM_GC if (gc_handles [i] != (gpointer)-1) GC_unregister_disappearing_link (&(gc_handles [i])); if (new_array [i] != (gpointer)-1) GC_GENERAL_REGISTER_DISAPPEARING_LINK (&(new_array [i]), REVEAL_POINTER (new_array [i])); +#endif } } } array_size *= 2; +#ifndef HAVE_BOEHM_GC + g_free (gc_handles); + g_free (gc_handle_types); +#endif gc_handles = new_array; gc_handle_types = new_type_array; -#else - LeaveCriticalSection (&handle_section); - mono_raise_exception (mono_get_exception_execution_engine ("No GCHandle support built-in")); -#endif } /* resuse the type from the old target */ @@ -399,9 +406,6 @@ ves_icall_System_GCHandle_GetTargetHandle (MonoObject *obj, guint32 handle, gint #if HAVE_BOEHM_GC if (gc_handles [idx] != (gpointer)-1) GC_GENERAL_REGISTER_DISAPPEARING_LINK (&(gc_handles [idx]), obj); -#else - LeaveCriticalSection (&handle_section); - mono_raise_exception (mono_get_exception_execution_engine ("No weakref support")); #endif break; default: @@ -429,9 +433,6 @@ ves_icall_System_GCHandle_FreeHandle (guint32 handle) if (gc_handles [idx] != (gpointer)-1) GC_unregister_disappearing_link (&(gc_handles [idx])); } -#else - LeaveCriticalSection (&handle_section); - mono_raise_exception (mono_get_exception_execution_engine ("No GCHandle support")); #endif gc_handles [idx] = (gpointer)-1; @@ -457,11 +458,50 @@ ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle) if (obj == (MonoObject *) -1) return NULL; } - return obj; + if (obj) { + MonoClass *klass = mono_object_class (obj); + if (klass == mono_defaults.string_class) { + return mono_string_chars ((MonoString*)obj); + } else if (klass->rank) { + return mono_array_addr ((MonoArray*)obj, char, 0); + } else { + /* the C# code will check and throw the exception */ + /* FIXME: missing !klass->blittable test, see bug #61134, + * disabled in 1.0 untill the blittable-using code is audited. + if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) + return (gpointer)-1; */ + return (char*)obj + sizeof (MonoObject); + } + } } return NULL; } +guint32 +mono_gchandle_new (MonoObject *obj, gboolean pinned) +{ + return ves_icall_System_GCHandle_GetTargetHandle (obj, 0, pinned? HANDLE_PINNED: HANDLE_NORMAL); +} + +guint32 +mono_gchandle_new_weakref (MonoObject *obj, gboolean track_resurrection) +{ + return ves_icall_System_GCHandle_GetTargetHandle (obj, 0, track_resurrection? HANDLE_WEAK_TRACK: HANDLE_WEAK); +} + +/* This will return NULL for a collected object if using a weakref handle */ +MonoObject* +mono_gchandle_get_target (guint32 gchandle) +{ + return ves_icall_System_GCHandle_GetTarget (gchandle); +} + +void +mono_gchandle_free (guint32 gchandle) +{ + ves_icall_System_GCHandle_FreeHandle (gchandle); +} + #if HAVE_BOEHM_GC static HANDLE finalizer_event; @@ -606,6 +646,12 @@ static GCThreadFunctions mono_gc_thread_vtable = { }; #endif /* WITH_INCLUDED_LIBGC */ +static void +mono_gc_warning (char *msg, GC_word arg) +{ + mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_GC, msg, (unsigned long)arg); +} + void mono_gc_init (void) { InitializeCriticalSection (&handle_section); @@ -617,6 +663,8 @@ void mono_gc_init (void) gc_thread_vtable = &mono_gc_thread_vtable; #endif + GC_set_warn_proc (mono_gc_warning); + #ifdef ENABLE_FINALIZER_THREAD if (g_getenv ("GC_DONT_GC")) { diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 8b0473429ed..01c9644be34 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -849,12 +849,12 @@ MonoImage * mono_image_open (const char *fname, MonoImageOpenStatus *status) { MonoImage *image, *image2; - const char *absfname; + char *absfname; g_return_val_if_fail (fname != NULL, NULL); if (g_path_is_absolute (fname)) - absfname = fname; + absfname = (char*)fname; else { gchar *path = g_get_current_dir (); absfname = g_build_filename (path, fname, NULL); @@ -960,9 +960,22 @@ mono_image_close (MonoImage *image) if (image->f) fclose (image->f); - if (image->raw_data_allocated) - g_free (image->raw_data); + if (image->raw_data_allocated) { + /* image->raw_metadata and cli_sections might lie inside image->raw_data */ + MonoCLIImageInfo *ii = image->image_info; + int i; + + if ((image->raw_metadata > image->raw_data) && + (image->raw_metadata <= (image->raw_data + image->raw_data_len))) + image->raw_metadata = NULL; + for (i = 0; i < ii->cli_section_count; i++) + if (((char*)(ii->cli_sections [i]) > image->raw_data) && + ((char*)(ii->cli_sections [i]) <= ((char*)image->raw_data + image->raw_data_len))) + ii->cli_sections [i] = NULL; + + g_free (image->raw_data); + } g_free (image->name); g_free (image->files); diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 81f2af3fa7c..f9fac307bd3 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -580,28 +580,41 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char g_assert (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL); - if (exc_class) { - *exc_class = NULL; - *exc_arg = NULL; - } - if (method->addr) return method->addr; - if (!piinfo->implmap_idx) - return NULL; - - mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE); - piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS]; - import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]); - scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME); - orig_scope = mono_metadata_string_heap (image, scope_token); + if (method->klass->image->dynamic) { + MonoReflectionMethodAux *method_aux = + mono_g_hash_table_lookup ( + ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method); + if (!method_aux) + return NULL; + + import = method_aux->dllentry; + orig_scope = method_aux->dll; + } + else { + if (!piinfo->implmap_idx) + return NULL; + + mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE); + + piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS]; + import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]); + scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME); + orig_scope = mono_metadata_string_heap (image, scope_token); + } mono_dllmap_lookup (image, orig_scope, import, &new_scope, &import); mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport attempting to load: '%s'.", new_scope); + if (exc_class) { + *exc_class = NULL; + *exc_arg = NULL; + } + #ifndef PLATFORM_WIN32 /* * If we are P/Invoking a library from System.Windows.Forms, load Wine @@ -616,17 +629,27 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char * Try loading the module using a variety of names */ for (i = 0; i < 2; ++i) { - if (i == 0) + switch (i) { + case 0: /* Try the original name */ file_name = g_strdup (new_scope); - else { + break; + case 1: /* Try trimming the .dll extension */ if (strstr (new_scope, ".dll") == (new_scope + strlen (new_scope) - 4)) { file_name = g_strdup (new_scope); file_name [strlen (new_scope) - 4] = '\0'; } else - break; + continue; + break; + default: + if (strstr (new_scope, "lib") != new_scope) { + file_name = g_strdup_printf ("lib%s", new_scope); + } + else + continue; + break; } if (!gmodule) { @@ -712,6 +735,21 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char break; } + +#ifdef PLATFORM_WIN32 + /* Try the stdcall mangled name */ + if (!method->addr) { + /* FIX: Compute this correctly */ + mangled_name = g_strdup_printf ("%s@%d", import, method->signature->param_count * sizeof (gpointer)); + g_module_symbol (gmodule, mangled_name, &method->addr); + g_free (mangled_name); + } + if (!method->addr) { + mangled_name = g_strdup_printf ("_%s@%d", import, method->signature->param_count * sizeof (gpointer)); + g_module_symbol (gmodule, mangled_name, &method->addr); + g_free (mangled_name); + } +#endif } if (!method->addr) { diff --git a/mono/metadata/locales.c b/mono/metadata/locales.c index 7c10529f3f3..256598e14c0 100644 --- a/mono/metadata/locales.c +++ b/mono/metadata/locales.c @@ -25,7 +25,7 @@ #include <locale.h> -//#undef DEBUG +#undef DEBUG static gint32 string_invariant_compare_char (gunichar2 c1, gunichar2 c2, gint32 options); @@ -1041,6 +1041,7 @@ void ves_icall_System_Globalization_CompareInfo_free_internal_collator (MonoComp coll=this->ICU_collator; if(coll!=NULL) { + this->ICU_collator = NULL; ucol_close (coll); } } @@ -1431,6 +1432,11 @@ MonoString *ves_icall_System_String_InternalReplace_Str_Comp (MonoString *this, * does match properly... */ match_len = usearch_getMatchedLength (search); + + if(match_len == 0) { + continue; + } + match=(UChar *)g_malloc0 (sizeof(UChar) * (match_len + 1)); usearch_getMatchedText (search, match, match_len, &ec); @@ -1467,6 +1473,11 @@ MonoString *ves_icall_System_String_InternalReplace_Str_Comp (MonoString *this, pos!=USEARCH_DONE; pos=usearch_next (search, &ec)) { match_len = usearch_getMatchedLength (search); + + if (match_len == 0) { + continue; + } + match=(UChar *)g_malloc0 (sizeof(UChar) * (match_len + 1)); usearch_getMatchedText (search, match, match_len, &ec); @@ -1865,15 +1876,6 @@ static gint32 string_invariant_compare_char (gunichar2 c1, gunichar2 c2, /* No options. Kana, symbol and spacing options don't * apply to the invariant culture. */ - if (c1type == G_UNICODE_UPPERCASE_LETTER && - c2type == G_UNICODE_LOWERCASE_LETTER) { - return(1); - } - - if (c1type == G_UNICODE_LOWERCASE_LETTER && - c2type == G_UNICODE_UPPERCASE_LETTER) { - return(-1); - } result = (gint32) c1 - c2; } diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 2892d81e88b..97a71e3a56a 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -2198,6 +2198,19 @@ handle_enum: return res; } +static void +raise_auto_layout_exception (MonoClass *klass) +{ + char *msg = g_strdup_printf ("The type `%s.%s' layout needs to be Sequential or Explicit", + klass->name_space, klass->name, NULL); + + MonoException *e = mono_exception_from_name_msg ( + mono_get_corlib (), "System.Runtime.InteropServices", + "MarshalDirectiveException", msg); + g_free (msg); + mono_raise_exception (e); +} + /* * generates IL code to call managed methods from unmanaged code */ @@ -2359,8 +2372,9 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMars break; } - /* FIXME: Raise a MarshalDirectiveException here */ - g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT); + /* The class can not have an automatic layout */ + if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) + raise_auto_layout_exception (klass); if (t->attrs & PARAM_ATTRIBUTE_OUT) { mono_mb_emit_byte (mb, CEE_LDNULL); @@ -2630,8 +2644,9 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMars break; } - /* FIXME: Raise a MarshalDirectiveException here */ - g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT); + /* The class can not have an automatic layout */ + if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) + raise_auto_layout_exception (klass); mono_mb_emit_byte (mb, CEE_STLOC_0); /* Check for null */ @@ -4845,6 +4860,8 @@ mono_marshal_alloc (gpointer size) { MONO_ARCH_SAVE_REGS; + if (size == NULL) + size = (gpointer)4; return g_try_malloc ((gulong)size); } diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index 88699f3e890..3d44463cde9 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -1203,6 +1203,10 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, { MonoType *type, *cached; gboolean byref = FALSE; + gboolean pinned = FALSE; + const char *tmp_ptr; + int count = 0; + gboolean found; /* * According to the spec, custom modifiers should come before the byref @@ -1212,70 +1216,70 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, * Also, this type seems to be different from 'object & modopt(...)'. Maybe * it would be better to treat byref as real type constructor instead of * a modifier... + * Also, pinned should come before anything else, but some MSV++ produced + * assemblies violate this (#bug 61990). */ - if (*ptr == MONO_TYPE_BYREF) { - byref = TRUE; - ++ptr; - } - switch (mode) { - case MONO_PARSE_MOD_TYPE: - case MONO_PARSE_PARAM: - case MONO_PARSE_RET: - case MONO_PARSE_LOCAL: /* should not have modifiers according to the spec, but ms tools disagree */ - case MONO_PARSE_FIELD: { - /* count the modifiers */ - const char *tmp_ptr = ptr; - int count = 0; - while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr)) - count++; - if (count) { - type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)); - type->num_mods = count; - if (count > 64) - g_warning ("got more than 64 modifiers in type"); - /* save them this time */ - count = 0; - while (mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr)) - count++; + /* Count the modifiers first */ + tmp_ptr = ptr; + found = TRUE; + while (found) { + switch (*tmp_ptr) { + case MONO_TYPE_PINNED: + case MONO_TYPE_BYREF: + ++tmp_ptr; + break; + case MONO_TYPE_CMOD_REQD: + case MONO_TYPE_CMOD_OPT: + count ++; + mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr); break; - } /* fall through */ + default: + found = FALSE; + } + } + + if (count) { + type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)); + type->num_mods = count; + if (count > 64) + g_warning ("got more than 64 modifiers in type"); } - case MONO_PARSE_TYPE: + else /* * Later we can avoid doing this allocation. */ type = g_new0 (MonoType, 1); - break; - default: - g_assert_not_reached (); + + /* Parse pinned, byref and custom modifiers */ + found = TRUE; + count = 0; + while (found) { + switch (*ptr) { + case MONO_TYPE_PINNED: + pinned = TRUE; + ++ptr; + break; + case MONO_TYPE_BYREF: + byref = TRUE; + ++ptr; + break; + case MONO_TYPE_CMOD_REQD: + case MONO_TYPE_CMOD_OPT: + count ++; + mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr); + break; + default: + found = FALSE; + } } type->attrs = opt_attrs; type->byref = byref; - if (mode == MONO_PARSE_LOCAL) { - /* - * check for pinned flag - */ - if (*ptr == MONO_TYPE_PINNED) { - type->pinned = 1; - ++ptr; - } - } + type->pinned = pinned ? 1 : 0; + + do_mono_metadata_parse_type (type, m, ptr, &ptr); - switch (*ptr) { - case MONO_TYPE_BYREF: - if (mode == MONO_PARSE_FIELD) - g_warning ("A field type cannot be byref"); - type->byref = 1; - ptr++; - /* follow through */ - default: - /*if (*ptr == MONO_TYPE_VOID && mode != MONO_PARSE_RET) - g_error ("void not allowed in param");*/ - do_mono_metadata_parse_type (type, m, ptr, &ptr); - break; - } if (rptr) *rptr = ptr; diff --git a/mono/metadata/mono-debug.c b/mono/metadata/mono-debug.c index b8503ecbc4b..b977ec0546d 100644 --- a/mono/metadata/mono-debug.c +++ b/mono/metadata/mono-debug.c @@ -45,8 +45,6 @@ extern void (*mono_debugger_class_init_func) (MonoClass *klass); void mono_debug_init (MonoDomain *domain, MonoDebugFormat format) { - MonoAssembly **ass; - g_assert (!mono_debug_initialized); mono_debug_initialized = TRUE; @@ -346,25 +344,35 @@ gchar * mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number, MonoDomain *domain) { - MonoDebugMethodInfo *minfo = _mono_debug_lookup_method (method); + char *res; + MonoDebugMethodInfo *minfo; MonoDebugDomainData *domain_data; - if (!minfo) + mono_loader_lock (); + minfo = _mono_debug_lookup_method (method); + if (!minfo || !minfo->handle || !minfo->handle->symfile || + !minfo->handle->symfile->offset_table) { + mono_loader_unlock (); return NULL; + } domain_data = mono_debug_get_domain_data (minfo->handle, domain); - if (!domain_data->jit [minfo->index]) + if (!domain_data->jit [minfo->index]) { + mono_loader_unlock (); return NULL; + } - if (minfo->handle) { + if (minfo->handle && minfo->handle->symfile) { gint32 offset = il_offset_from_address (domain_data->jit [minfo->index], address); + char *res = NULL; - if (offset < 0) - return NULL; - - return mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number); + if (offset >= 0) + res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number); + mono_loader_unlock (); + return res; } + mono_loader_unlock (); return NULL; } @@ -381,12 +389,19 @@ mono_debug_source_location_from_address (MonoMethod *method, guint32 address, gu gchar * mono_debug_source_location_from_il_offset (MonoMethod *method, guint32 offset, guint32 *line_number) { - MonoDebugMethodInfo *minfo = _mono_debug_lookup_method (method); + char *res; + MonoDebugMethodInfo *minfo; - if (!minfo || !minfo->handle) + mono_loader_lock (); + minfo = _mono_debug_lookup_method (method); + if (!minfo || !minfo->handle || !minfo->handle->symfile) { + mono_loader_unlock (); return NULL; + } - return mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number); + res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number); + mono_loader_unlock (); + return res; } /* @@ -398,17 +413,24 @@ mono_debug_il_offset_from_address (MonoMethod *method, gint32 address, MonoDomai { MonoDebugMethodInfo *minfo; MonoDebugDomainData *domain_data; + gint32 res; if (address < 0) return -1; + mono_loader_lock (); minfo = _mono_debug_lookup_method (method); - if (!minfo || !minfo->il_offsets) + if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile || + !minfo->handle->symfile->offset_table) { + mono_loader_unlock (); return -1; + } domain_data = mono_debug_get_domain_data (minfo->handle, domain); - return il_offset_from_address (domain_data->jit [minfo->index], address); + res = il_offset_from_address (domain_data->jit [minfo->index], address); + mono_loader_unlock (); + return res; } /* @@ -420,17 +442,24 @@ mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset, MonoDom { MonoDebugMethodInfo *minfo; MonoDebugDomainData *domain_data; + gint32 res; if (il_offset < 0) return -1; + mono_loader_lock (); minfo = _mono_debug_lookup_method (method); - if (!minfo || !minfo->il_offsets) + if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile || + !minfo->handle->symfile->offset_table) { + mono_loader_unlock (); return -1; + } domain_data = mono_debug_get_domain_data (minfo->handle, domain); - return _mono_debug_address_from_il_offset (domain_data->jit [minfo->index], il_offset); + res = _mono_debug_address_from_il_offset (domain_data->jit [minfo->index], il_offset); + mono_loader_unlock (); + return res; } MonoDebugDomainData * @@ -439,6 +468,9 @@ mono_debug_get_domain_data (MonoDebugHandle *handle, MonoDomain *domain) MonoDebugDomainData *data; int domain_id = mono_domain_get_id (domain); + /* We checked this earlier. */ + g_assert (handle->symfile); + for (data = handle->_priv->domain_table; data; data = data->_priv->next) if (data->domain_id == domain_id) return data; diff --git a/mono/metadata/object.c b/mono/metadata/object.c index bdf832baa6d..904bd25c868 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -90,6 +90,7 @@ typedef struct { guint32 initializing_tid; guint32 waiting_count; + gboolean done; CRITICAL_SECTION initialization_section; } TypeInitializationLock; @@ -177,28 +178,38 @@ mono_runtime_class_init (MonoVTable *vtable) InitializeCriticalSection (&lock->initialization_section); lock->initializing_tid = tid; lock->waiting_count = 1; + lock->done = FALSE; /* grab the vtable lock while this thread still owns type_initialization_section */ EnterCriticalSection (&lock->initialization_section); g_hash_table_insert (type_initialization_hash, vtable, lock); do_initialization = 1; } else { gpointer blocked; + TypeInitializationLock *pending_lock; - if (lock->initializing_tid == tid) { + if (lock->initializing_tid == tid || lock->done) { LeaveCriticalSection (&type_initialization_section); return; } /* see if the thread doing the initialization is already blocked on this thread */ blocked = GUINT_TO_POINTER (lock->initializing_tid); - while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) { - if (blocked == GUINT_TO_POINTER (tid)) { - LeaveCriticalSection (&type_initialization_section); - return; + while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) { + if (pending_lock->initializing_tid == tid) { + if (!pending_lock->done) { + LeaveCriticalSection (&type_initialization_section); + return; + } else { + /* the thread doing the initialization is blocked on this thread, + but on a lock that has already been freed. It just hasn't got + time to awake */ + break; + } } + blocked = GUINT_TO_POINTER (pending_lock->initializing_tid); } ++lock->waiting_count; /* record the fact that we are waiting on the initializing thread */ - g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid)); + g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock); } LeaveCriticalSection (&type_initialization_section); @@ -206,6 +217,7 @@ mono_runtime_class_init (MonoVTable *vtable) mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc); if (last_domain) mono_domain_set (last_domain, TRUE); + lock->done = TRUE; LeaveCriticalSection (&lock->initialization_section); } else { /* this just blocks until the initializing thread is done */ @@ -1586,13 +1598,9 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params, case MONO_TYPE_R4: case MONO_TYPE_R8: case MONO_TYPE_VALUETYPE: - if (sig->params [i]->byref) { - /* MS seems to create the objects if a null is passed in */ - if (! ((gpointer *)params->vector)[i]) - ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i])); - } - else - g_assert (((gpointer*)params->vector) [i]); + /* MS seems to create the objects if a null is passed in */ + if (! ((gpointer *)params->vector)[i]) + ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i])); pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject); break; case MONO_TYPE_STRING: @@ -2715,6 +2723,7 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, MonoDomain *domain; MonoMethod *method; MonoMethodSignature *sig; + MonoObject *ret; int i, j, outarg_count = 0; if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) { @@ -2739,6 +2748,8 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count); *exc = NULL; + ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc); + for (i = 0, j = 0; i < sig->param_count; i++) { if (sig->params [i]->byref) { gpointer arg; @@ -2748,7 +2759,7 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, } } - return mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc); + return ret; } void diff --git a/mono/metadata/object.h b/mono/metadata/object.h index c1ffc3c4c2d..2413cc7a346 100644 --- a/mono/metadata/object.h +++ b/mono/metadata/object.h @@ -252,5 +252,11 @@ mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObjec MonoObject* mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc); +/* GC handles support */ +guint32 mono_gchandle_new (MonoObject *obj, gboolean pinned); +guint32 mono_gchandle_new_weakref (MonoObject *obj, gboolean track_resurrection); +MonoObject* mono_gchandle_get_target (guint32 gchandle); +void mono_gchandle_free (guint32 gchandle); + #endif diff --git a/mono/metadata/process.c b/mono/metadata/process.c index 5e7cce9de7b..5fa57bcf0ed 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -738,7 +738,7 @@ complete_path (const gunichar2 *appname, gunichar2 **completed) return FALSE; } - if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE)) { + if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) { g_free (utf8app); return FALSE; } @@ -875,7 +875,9 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *app if(ret) { process_info->process_handle=procinfo.hProcess; - process_info->thread_handle=procinfo.hThread; + /*process_info->thread_handle=procinfo.hThread;*/ + process_info->thread_handle=NULL; + CloseHandle(procinfo.hThread); process_info->pid=procinfo.dwProcessId; process_info->tid=procinfo.dwThreadId; } else { diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 9640136c0eb..9a1555d27a7 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -61,6 +61,9 @@ typedef struct { MonoMethod *mhandle; guint32 nrefs; gpointer *refs; + /* for PInvoke */ + int charset, lasterr, native_cc; + MonoString *dll, *dllentry; } ReflectionMethodBuilder; const unsigned char table_sizes [64] = { @@ -887,6 +890,8 @@ method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb) max_stack = 8; /* we probably need to run a verifier on the code... */ } + stream_data_align (&assembly->code); + /* check for exceptions, maxstack, locals */ maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception); if (maybe_small) { @@ -1260,6 +1265,14 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, rmb->mhandle = mb->mhandle; rmb->nrefs = 0; rmb->refs = NULL; + + if (mb->dll) { + rmb->charset = rmb->charset & 0xf; + rmb->lasterr = rmb->charset & 0x40; + rmb->native_cc = rmb->native_cc; + rmb->dllentry = mb->dllentry; + rmb->dll = mb->dll; + } } static void @@ -2716,7 +2729,8 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon * if we have explicitlayout or sequentiallayouts, output data in the * ClassLayout table. */ - if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) { + if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && + ((tb->class_size > 0) || (tb->packing_size > 0))) { table = &assembly->tables [MONO_TABLE_CLASSLAYOUT]; table->rows++; alloc_table (table, table->rows); @@ -5256,12 +5270,21 @@ MonoArray* mono_param_get_objects (MonoDomain *domain, MonoMethod *method) { static MonoClass *System_Reflection_ParameterInfo; + static MonoClassField *dbnull_value_field; + MonoClass *klass; MonoArray *res = NULL; MonoReflectionMethod *member = NULL; MonoReflectionParameter *param = NULL; char **names; int i; + if (!dbnull_value_field) { + klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull"); + mono_class_init (klass); + dbnull_value_field = mono_class_get_field_from_name (klass, "Value"); + g_assert (dbnull_value_field); + } + if (!System_Reflection_ParameterInfo) System_Reflection_ParameterInfo = mono_class_from_name ( mono_defaults.corlib, "System.Reflection", "ParameterInfo"); @@ -5283,7 +5306,7 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method) param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo); param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]); - param->DefaultValueImpl = NULL; /* FIXME */ + param->DefaultValueImpl = mono_field_get_value_object (domain, dbnull_value_field, NULL); /* FIXME */ param->MemberImpl = (MonoObject*)member; param->NameImpl = mono_string_new (domain, names [i]); param->PositionImpl = i; @@ -5868,6 +5891,7 @@ handle_type: } break; case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: case MONO_TYPE_STRING: for (i = 0; i < alen; i++) { MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p); @@ -7005,6 +7029,17 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) { /* TODO */ m->signature->pinvoke = 1; + + method_aux = g_new0 (MonoReflectionMethodAux, 1); + + method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry)); + method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll)); + + ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr; + + if (klass->image->dynamic) + mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux); + return m; } else if (!m->klass->dummy && !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) && @@ -7818,6 +7853,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) { MonoClass *klass; MonoReflectionType* res; + int i; MONO_ARCH_SAVE_REGS; @@ -7828,7 +7864,6 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) /* * Fields to set in klass: * the various flags: delegate/unicode/contextbound etc. - * nested_classes */ klass->flags = tb->attrs; @@ -7840,6 +7875,13 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) if (!klass->enumtype) ensure_runtime_vtable (klass); + if (tb->subtypes) { + for (i = 0; i < mono_array_length (tb->subtypes); ++i) { + MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i); + klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type)); + } + } + /* fields and object layout */ if (klass->parent) { if (!klass->parent->size_inited) diff --git a/mono/metadata/reflection.h b/mono/metadata/reflection.h index e44243f3d66..f365047c3b6 100644 --- a/mono/metadata/reflection.h +++ b/mono/metadata/reflection.h @@ -34,6 +34,7 @@ typedef struct { char **param_names; MonoMarshalSpec **param_marshall; MonoCustomAttrInfo **param_cattr; + char *dllentry, *dll; } MonoReflectionMethodAux; int mono_reflection_parse_type (char *name, MonoTypeNameParse *info); diff --git a/mono/metadata/socket-io.c b/mono/metadata/socket-io.c index c2b129984e7..1ef49278ea9 100644 --- a/mono/metadata/socket-io.c +++ b/mono/metadata/socket-io.c @@ -330,6 +330,11 @@ static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level, case SocketOptionName_Type: *system_name = SO_TYPE; break; +#ifdef SO_PEERCRED + case SocketOptionName_PeerCred: + *system_name = SO_PEERCRED; + break; +#endif case SocketOptionName_ExclusiveAddressUse: case SocketOptionName_UseLoopback: case SocketOptionName_MaxConnections: @@ -1155,7 +1160,15 @@ gint32 ves_icall_System_Net_Sockets_Socket_RecvFrom_internal(SOCKET sock, MonoAr return(0); } - *sockaddr=create_object_from_sockaddr(sa, sa_size, error); + /* If we didn't get a socket size, then we're probably a + * connected connection-oriented socket and the stack hasn't + * returned the remote address. All we can do is return null. + */ + if ( sa_size != 0 ) + *sockaddr=create_object_from_sockaddr(sa, sa_size, error); + else + *sockaddr=NULL; + g_free(sa); return(ret); @@ -1428,6 +1441,10 @@ void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET soc int lingersize=sizeof(linger); struct timeval tv; int tvsize=sizeof(tv); +#ifdef SO_PEERCRED + struct ucred cred; + int credsize = sizeof(cred); +#endif MonoDomain *domain=mono_domain_get(); MonoObject *obj; MonoClass *obj_class; @@ -1461,6 +1478,13 @@ void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET soc &tvsize); break; +#ifdef SO_PEERCRED + case SocketOptionName_PeerCred: + ret = _wapi_getsockopt (sock, system_level, system_name, &cred, + &credsize); + break; +#endif + default: ret = _wapi_getsockopt (sock, system_level, system_name, &val, &valsize); @@ -1500,6 +1524,32 @@ void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET soc obj = int_to_object (domain, (tv.tv_sec * 1000) + (tv.tv_usec / 1000)); break; +#ifdef SO_PEERCRED + case SocketOptionName_PeerCred: + { + /* build a Mono.Posix.PeerCred+PeerCredData if + * possible + */ + MonoImage *mono_posix_image = mono_image_loaded ("Mono.Posix"); + MonoPeerCredData *cred_data; + + if (mono_posix_image == NULL) { + *error = WSAENOPROTOOPT; + return; + } + + obj_class = mono_class_from_name(mono_posix_image, + "Mono.Posix", + "PeerCred/PeerCredData"); + obj = mono_object_new(domain, obj_class); + cred_data = (MonoPeerCredData *)obj; + cred_data->pid = cred.pid; + cred_data->uid = cred.uid; + cred_data->gid = cred.gid; + break; + } +#endif + default: obj = int_to_object (domain, val); } diff --git a/mono/metadata/socket-io.h b/mono/metadata/socket-io.h index 3540882f105..5c2ee72181a 100644 --- a/mono/metadata/socket-io.h +++ b/mono/metadata/socket-io.h @@ -130,7 +130,12 @@ typedef enum { SocketOptionName_BsdUrgent=2, SocketOptionName_Expedited=2, SocketOptionName_NoChecksum=1, - SocketOptionName_ChecksumCoverage=20 + SocketOptionName_ChecksumCoverage=20, + + /* This is Mono-specific, keep it in sync with + * Mono.Posix/PeerCred.cs + */ + SocketOptionName_PeerCred=10001 } MonoSocketOptionName; typedef struct _MonoSocketAsyncResult { @@ -154,6 +159,14 @@ typedef struct _MonoSocketAsyncResult { gint error; } MonoSocketAsyncResult; +typedef struct +{ + MonoObject obj; + gint pid; + gint uid; + gint gid; +} MonoPeerCredData; + extern gpointer ves_icall_System_Net_Sockets_Socket_Socket_internal(MonoObject *this, gint32 family, gint32 type, gint32 proto, gint32 *error); extern void ves_icall_System_Net_Sockets_Socket_Close_internal(SOCKET sock, gint32 *error); extern gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal(void); diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index e14470c0e5d..9d5768df224 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -31,7 +31,7 @@ #include "threadpool.h" /* maximum number of worker threads */ -int mono_max_worker_threads = 25; /* fixme: should be 25 per available CPU */ +int mono_max_worker_threads = 25; /* per available CPU? */ static int mono_min_worker_threads = 0; /* current number of worker threads */ @@ -43,6 +43,8 @@ static int busy_worker_threads = 0; /* we use this to store a reference to the AsyncResult to avoid GC */ static MonoGHashTable *ares_htable = NULL; +static CRITICAL_SECTION ares_lock; + /* we append a job */ static HANDLE job_added; @@ -91,9 +93,12 @@ mono_async_invoke (MonoAsyncResult *ares) } mono_monitor_exit ((MonoObject *) ares); + EnterCriticalSection (&ares_lock); mono_g_hash_table_remove (ares_htable, ares); + LeaveCriticalSection (&ares_lock); } + MonoAsyncResult * mono_thread_pool_add (MonoObject *target, MonoMethodMessage *msg, MonoDelegate *async_callback, MonoObject *state) @@ -122,11 +127,14 @@ mono_thread_pool_add (MonoObject *target, MonoMethodMessage *msg, MonoDelegate * ares->async_delegate = target; if (!ares_htable) { + InitializeCriticalSection (&ares_lock); ares_htable = mono_g_hash_table_new (NULL, NULL); job_added = CreateSemaphore (NULL, 0, 0x7fffffff, NULL); } + EnterCriticalSection (&ares_lock); mono_g_hash_table_insert (ares_htable, ares, ares); + LeaveCriticalSection (&ares_lock); busy = (int) InterlockedCompareExchange (&busy_worker_threads, 0, -1); worker = (int) InterlockedCompareExchange (&mono_worker_threads, 0, -1); @@ -203,8 +211,19 @@ mono_thread_pool_cleanup (void) static void append_job (MonoAsyncResult *ar) { + GList *tmp; + EnterCriticalSection (&mono_delegate_section); - async_call_queue = g_list_append (async_call_queue, ar); + if (async_call_queue == NULL) { + async_call_queue = g_list_append (async_call_queue, ar); + } else { + for (tmp = async_call_queue; tmp && tmp->data != NULL; tmp = tmp->next); + if (tmp == NULL) { + async_call_queue = g_list_append (async_call_queue, ar); + } else { + tmp->data = ar; + } + } LeaveCriticalSection (&mono_delegate_section); } @@ -212,17 +231,23 @@ static MonoAsyncResult * dequeue_job (void) { MonoAsyncResult *ar = NULL; - GList *tmp = NULL; + GList *tmp, *tmp2; EnterCriticalSection (&mono_delegate_section); - if (async_call_queue) { - ar = (MonoAsyncResult *)async_call_queue->data; - tmp = async_call_queue; - async_call_queue = g_list_remove_link (tmp, tmp); + tmp = async_call_queue; + if (tmp) { + ar = (MonoAsyncResult *) tmp->data; + tmp->data = NULL; + tmp2 = tmp; + for (tmp2 = tmp; tmp2->next != NULL; tmp2 = tmp2->next); + if (tmp2 != tmp) { + async_call_queue = tmp->next; + tmp->next = NULL; + tmp2->next = tmp; + tmp->prev = tmp2; + } } LeaveCriticalSection (&mono_delegate_section); - if (tmp) - g_list_free_1 (tmp); return ar; } @@ -268,7 +293,7 @@ async_invoke_thread (gpointer data) } while (!data && timeout > 0); } - + if (!data) { workers = (int) InterlockedCompareExchange (&mono_worker_threads, 0, -1); min = (int) InterlockedCompareExchange (&mono_min_worker_threads, 0, -1); diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 7a43ab5ff8a..26568288af1 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -243,12 +243,9 @@ static guint32 start_wrapper(void *data) mono_thread_push_appdomain_ref (mono_domain_get ()); thread_adjust_static_data (thread); -#ifndef PLATFORM_WIN32 #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION "start_wrapper for %d\n", thread->tid); #endif - pthread_cleanup_push ((void (*) (void *)) mono_thread_detach, thread); -#endif start_func (this); #ifdef PLATFORM_WIN32 @@ -273,8 +270,6 @@ static guint32 start_wrapper(void *data) TlsSetValue (current_object_key, NULL); thread_cleanup (thread); -#else - pthread_cleanup_pop (1); #endif return(0); diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index cdcd480a069..8e09b509dbc 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,68 @@ +2004-09-17 Zoltan Varga <vargaz@freemail.hu> + + * mini.c (mono_method_to_ir): Fix LDSTR in dynamic methods. Fixes #66132. + +2004-09-11 Ben Maurer <bmaurer@users.sourceforge.net> + + * inssel.brg: make ldelema check aot friendly. + +Thu Sep 9 20:57:53 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * mini-*.c, mini-ops.h, inssel-long32.brg: introduced + OP_ADDCC_IMM and OP_SUBCC_IMM (add/sub immediate that will + set the carry/borrow flag). The sparc and s390 implementations + can now use optimized versions (and simplify the code). ppc bugfixes. + +2004-09-02 Zoltan Varga <vargaz@freemail.hu> + + * inssel-long32.brg: Fix OP_LCONV_TO_OVF_I1 rule. Fixes #64578. + +2004-08-23 Zoltan Varga <vargaz@freemail.hu> + + * inssel-x86.brg inssel-amd64: Add yet another missing tree->dreg assignment. + + * mini-x86.c (mono_arch_local_regalloc): Fix bug in long register + allocation. Fixes #63085. + +2004-08-09 Zoltan Varga <vargaz@freemail.hu> + + * inssel-x86.brg: Set dreg of LOCALLOC correctly. + +Tue Aug 3 11:20:09 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * mini-ppc.c: mul.ovf.un exception name fix. + +Tue Aug 3 11:19:07 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * mini-ppc.c: reg allocator fix. + +Tue Aug 3 11:17:07 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * mini-ppc.c: make sure temp regs are not used for global reg + allocation. + +Tue Jul 27 16:05:19 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * mini-ppc.c, mini-sparc.c, mini-s390.c: keep track of line + numbers in the debug info (spotted by Geoff Norton, + <gnorton@customerdna.com>). + +Mon Jul 12 17:47:00 CEST 2004 Paolo Molaro <lupus@ximian.com> + + * inssel-ppc.brg: arguments on the stack are always + relative to the stack pointer (spotted by Neale Ferguson). + +2004-07-11 Gonzalo Paniagua Javier <gonzalo@ximian.com> + + * exceptions-x86.c: delay appending the method name to the trace until + after mono_jit_info_table_find is called, as this gets the real + MonoMethod. + +2004-07-08 Zoltan Varga <vargaz@freemail.hu> + + * mini.c (handle_stack_args): Handle some corner cases. Fixes + 58863. + 2004-07-05 Zoltan Varga <vargaz@freemail.hu> * mini.c (optimize_branches): Fix linking of bblocks in branch->branch diff --git a/mono/mini/basic-long.cs b/mono/mini/basic-long.cs index f16f9f5dcb1..4b321017ce7 100644 --- a/mono/mini/basic-long.cs +++ b/mono/mini/basic-long.cs @@ -263,6 +263,12 @@ class Tests { return 1; } + static int test_4_addcc_imm () { + long a = 3; + long b = 0; + return (int)(a - b + 1); + } + static int test_5_sub () { long a = 8; long b = 3; diff --git a/mono/mini/cpu-g4.md b/mono/mini/cpu-g4.md index 7d76db87792..638fb2828bc 100644 --- a/mono/mini/cpu-g4.md +++ b/mono/mini/cpu-g4.md @@ -545,6 +545,8 @@ adc: dest:i src1:i src2:i len:4 addcc: dest:i src1:i src2:i len:4 subcc: dest:i src1:i src2:i len:4 adc_imm: dest:i src1:i len:12 +addcc_imm: dest:i src1:i len:12 +subcc_imm: dest:i src1:i len:12 sbb: dest:i src1:i src2:i len:4 sbb_imm: dest:i src1:i len:12 br_reg: src1:i len:8 diff --git a/mono/mini/cpu-pentium.md b/mono/mini/cpu-pentium.md index 2568eac81f6..e48ba96540e 100644 --- a/mono/mini/cpu-pentium.md +++ b/mono/mini/cpu-pentium.md @@ -354,7 +354,9 @@ loadr8_membase: dest:f src1:b len:6 loadr8_spill_membase: src1:b len:8 loadu4_mem: dest:i len:9 move: dest:i src1:i len:2 +addcc_imm: dest:i src1:i len:6 clob:1 add_imm: dest:i src1:i len:6 clob:1 +subcc_imm: dest:i src1:i len:6 clob:1 sub_imm: dest:i src1:i len:6 clob:1 mul_imm: dest:i src1:i len:6 # there is no actual support for division or reminder by immediate diff --git a/mono/mini/cpu-s390.md b/mono/mini/cpu-s390.md index 256bf4aa609..3cc63d770d1 100644 --- a/mono/mini/cpu-s390.md +++ b/mono/mini/cpu-s390.md @@ -349,7 +349,9 @@ loadu4_mem: dest:i len:8 move: dest:i src1:i len:4 fmove: dest:f src1:f len:4 add_imm: dest:i src1:i len:18 +addcc_imm: dest:i src1:i len:18 sub_imm: dest:i src1:i len:18 +subcc_imm: dest:i src1:i len:18 mul_imm: dest:i src1:i len:18 # there is no actual support for division or reminder by immediate # we simulate them, though (but we need to change the burg rules diff --git a/mono/mini/cpu-sparc.md b/mono/mini/cpu-sparc.md index 8f9280a222b..6fef70d713d 100644 --- a/mono/mini/cpu-sparc.md +++ b/mono/mini/cpu-sparc.md @@ -356,7 +356,9 @@ loadr8_membase: dest:f src1:b len:20 loadu4_mem: dest:i len:8 move: dest:i src1:i len:4 add_imm: dest:i src1:i len:12 +addcc_imm: dest:i src1:i len:64 sub_imm: dest:i src1:i len:12 +subcc_imm: dest:i src1:i len:64 mul_imm: dest:i src1:i len:12 div_imm: dest:a src1:i src2:i len:28 div_un_imm: dest:a src1:i src2:i len:12 diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index b0783ae39b1..c0961c485d2 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -462,9 +462,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf if (!(*lmf)->method) return (gpointer)-1; - if (trace) - *trace = g_strdup_printf ("in (unmanaged) %s", mono_method_full_name ((*lmf)->method, TRUE)); - if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) { *res = *ji; } else { @@ -472,6 +469,9 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf res->method = (*lmf)->method; } + if (trace) + *trace = g_strdup_printf ("in (unmanaged) %s", mono_method_full_name (res->method, TRUE)); + new_ctx->SC_ESI = (*lmf)->esi; new_ctx->SC_EDI = (*lmf)->edi; new_ctx->SC_EBX = (*lmf)->ebx; diff --git a/mono/mini/inssel-long32.brg b/mono/mini/inssel-long32.brg index 0d1cf077f2d..2ebeb3c27b7 100644 --- a/mono/mini/inssel-long32.brg +++ b/mono/mini/inssel-long32.brg @@ -108,7 +108,7 @@ lreg: OP_LADD_OVF_UN (lreg, lreg) { } lreg: OP_LADD (lreg, i8con) { - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADDCC_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); MONO_EMIT_BIALU_IMM (s, tree, OP_ADC_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word); } @@ -118,7 +118,7 @@ lreg: OP_LSUB (lreg, lreg) { } lreg: OP_LSUB (lreg, i8con) { - MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); + MONO_EMIT_NEW_BIALU_IMM (s, OP_SUBCC_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); MONO_EMIT_BIALU_IMM (s, tree, OP_SBB_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word); } @@ -575,15 +575,30 @@ reg: OP_LCONV_TO_OVF_I1_UN (lreg) { } reg: OP_LCONV_TO_OVF_I1 (lreg) { + MonoInst *is_negative, *end_label; + + MONO_NEW_LABEL (s, is_negative); + MONO_NEW_LABEL (s, end_label); + MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0); MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException"); MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1); MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException"); + MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0); + MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT, is_negative); + + /* Positive */ MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127); - MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException"); + MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label); + + /* Negative */ + mono_bblock_add_inst (s->cbb, is_negative); MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128); - MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (s, LT_UN, "OverflowException"); + mono_bblock_add_inst (s->cbb, end_label); + MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1); } diff --git a/mono/mini/inssel-ppc.brg b/mono/mini/inssel-ppc.brg index a4043e1d797..38eced8c0dc 100644 --- a/mono/mini/inssel-ppc.brg +++ b/mono/mini/inssel-ppc.brg @@ -131,7 +131,7 @@ stmt: OP_SETRET (OP_ICONST) { stmt: OP_OUTARG (reg) { if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, tree->inst_imm, state->left->reg1); return; } tree->opcode = OP_SETREG; @@ -142,7 +142,7 @@ stmt: OP_OUTARG (reg) { stmt: OP_OUTARG (OP_REGVAR) { if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->tree->dreg); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, tree->inst_imm, state->left->tree->dreg); return; } tree->opcode = OP_SETREG; @@ -153,8 +153,8 @@ stmt: OP_OUTARG (OP_REGVAR) { stmt: OP_OUTARG (lreg) { if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg2); - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm + 4, state->left->reg1); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, tree->inst_imm, state->left->reg2); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, tree->inst_imm + 4, state->left->reg1); return; } MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2); @@ -166,7 +166,7 @@ stmt: OP_OUTARG (lreg) { stmt: OP_OUTARG (OP_ICONST) { if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, s->frame_reg, tree->inst_imm, state->left->tree->inst_c0); + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, ppc_r1, tree->inst_imm, state->left->tree->inst_c0); return; } tree->opcode = OP_SETREGIMM; @@ -205,7 +205,7 @@ stmt: OP_OUTARG (OP_ICONST) { stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) { if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->left->tree->dreg); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ppc_r1, tree->inst_imm, state->left->left->tree->dreg); return; } tree->opcode = OP_SETREG; @@ -223,7 +223,7 @@ stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) { stmt: OP_OUTARG (freg) { if (tree->inst_imm) { int opcode = (tree->unused & 0xff00) == 0x0400? OP_STORER4_MEMBASE_REG: OP_STORER8_MEMBASE_REG; - MONO_EMIT_NEW_STORE_MEMBASE (s, opcode, s->frame_reg, tree->inst_imm, state->left->reg1); + MONO_EMIT_NEW_STORE_MEMBASE (s, opcode, ppc_r1, tree->inst_imm, state->left->reg1); return; } tree->opcode = OP_SETFREG; @@ -234,7 +234,7 @@ stmt: OP_OUTARG (freg) { stmt: OP_OUTARG_R4 (freg) { if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, ppc_r1, tree->inst_imm, state->left->reg1); return; } tree->opcode = OP_SETFREG; @@ -245,7 +245,7 @@ stmt: OP_OUTARG_R4 (freg) { stmt: OP_OUTARG_R8 (freg) { if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, ppc_r1, tree->inst_imm, state->left->reg1); return; } tree->opcode = OP_SETFREG; @@ -269,7 +269,7 @@ stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) { } //g_print ("vt size: %d at R%d + %d\n", tree->inst_imm, vt->inst_basereg, vt->inst_offset); if (ovf_size != 0) { - mini_emit_memcpy (s, s->frame_reg, tree->inst_imm + (soffset - vt->inst_offset), vt->inst_basereg, soffset, ovf_size * sizeof (gpointer), 0); + mini_emit_memcpy (s, ppc_r1, tree->inst_imm + (soffset - vt->inst_offset), vt->inst_basereg, soffset, ovf_size * sizeof (gpointer), 0); } } diff --git a/mono/mini/inssel-x86.brg b/mono/mini/inssel-x86.brg index b1f1cf67c77..b80affe25ab 100644 --- a/mono/mini/inssel-x86.brg +++ b/mono/mini/inssel-x86.brg @@ -151,6 +151,7 @@ reg: OP_LOCALLOC (OP_ICONST) { if (tree->flags & MONO_INST_INIT) { /* microcoded in mini-x86.c */ tree->sreg1 = mono_regstate_next_int (s->rs); + tree->dreg = state->reg1; MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0); mono_bblock_add_inst (s->cbb, tree); } else { @@ -161,6 +162,7 @@ reg: OP_LOCALLOC (OP_ICONST) { reg: OP_LOCALLOC (reg) { tree->sreg1 = state->left->tree->dreg; + tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } diff --git a/mono/mini/inssel.brg b/mono/mini/inssel.brg index e0bc1f0254b..0cb8129cca0 100644 --- a/mono/mini/inssel.brg +++ b/mono/mini/inssel.brg @@ -1736,7 +1736,14 @@ reg: OP_CHECK_ARRAY_TYPE (reg) { vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass)); MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, elclass_reg, class_reg, G_STRUCT_OFFSET (MonoClass, element_class)); - MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, elclass_reg, tree->klass); + if (mono_compile_aot) { + int klass_reg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_CLASSCONST (s, klass_reg, tree->klass); + MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, elclass_reg, klass_reg); + } else { + MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, elclass_reg, tree->klass); + } + MONO_EMIT_NEW_COND_EXC (s, NE_UN, "ArrayTypeMismatchException"); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } diff --git a/mono/mini/mini-ops.h b/mono/mini/mini-ops.h index 32b6eb5f35e..98da133d3fa 100644 --- a/mono/mini/mini-ops.h +++ b/mono/mini/mini-ops.h @@ -297,7 +297,9 @@ MINI_OP(OP_ADC_IMM, "adc_imm") MINI_OP(OP_SBB, "sbb") MINI_OP(OP_SBB_IMM, "sbb_imm") MINI_OP(OP_ADDCC, "addcc") +MINI_OP(OP_ADDCC_IMM, "addcc_imm") MINI_OP(OP_SUBCC, "subcc") +MINI_OP(OP_SUBCC_IMM, "subcc_imm") MINI_OP(OP_BR_REG, "br_reg") MINI_OP(OP_SEXT_I1, "sext_i1") MINI_OP(OP_SEXT_I2, "sext_i2") diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c index a62d49bd453..92bef163894 100644 --- a/mono/mini/mini-ppc.c +++ b/mono/mini/mini-ppc.c @@ -209,7 +209,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) if (cfg->frame_reg != ppc_sp) top = 31; #if USE_EXTRA_TEMPS - top -= 2; + top = 29; #endif for (i = 13; i < top; ++i) regs = g_list_prepend (regs, GUINT_TO_POINTER (i)); @@ -1296,7 +1296,11 @@ mono_spillvar_offset_float (MonoCompile *cfg, int spillvar) #undef DEBUG #define DEBUG(a) if (cfg->verbose_level > 1) a //#define DEBUG(a) -#define reg_is_freeable(r) ((r) >= 3 && (r) <= 10) +/* use ppc_r3-ppc_10,ppc_r12 as temp registers, f1-f13 for FP registers */ +#define PPC_CALLER_REGS ((0xff<<3) | (1<<12) | USE_EXTRA_TEMPS) +#define PPC_CALLER_FREGS (0x3ffe) + +#define reg_is_freeable(r) (PPC_CALLER_REGS & 1 << (r)) #define freg_is_freeable(r) ((r) >= 1 && (r) <= 13) typedef struct { @@ -1631,10 +1635,6 @@ alloc_int_reg (MonoCompile *cfg, InstList *curinst, MonoInst *ins, int sym_reg, return val; } -/* use ppc_r3-ppc_10,ppc_r12 as temp registers, f1-f13 for FP registers */ -#define PPC_CALLER_REGS ((0xff<<3) | (1<<12) | USE_EXTRA_TEMPS) -#define PPC_CALLER_FREGS (0x3ffe) - /* * Local register allocation. * We first scan the list of instructions and we save the liveness info of @@ -2275,6 +2275,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } // if (ins->cil_code) // g_print ("cil code\n"); + mono_debug_record_line_number (cfg, ins, offset); switch (ins->opcode) { case OP_BIGMUL: @@ -2442,6 +2443,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_ADC: ppc_adde (code, ins->dreg, ins->sreg1, ins->sreg2); break; + case OP_ADDCC_IMM: + if (ppc_is_imm16 (ins->inst_imm)) { + ppc_addic (code, ins->dreg, ins->sreg1, ins->inst_imm); + } else { + ppc_load (code, ppc_r11, ins->inst_imm); + ppc_addc (code, ins->dreg, ins->sreg1, ppc_r11); + } + break; case OP_ADD_IMM: if (ppc_is_imm16 (ins->inst_imm)) { ppc_addi (code, ins->dreg, ins->sreg1, ins->inst_imm); @@ -2521,6 +2530,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_SUBCC: ppc_subfc (code, ins->dreg, ins->sreg2, ins->sreg1); break; + case OP_SUBCC_IMM: + ppc_load (code, ppc_r11, ins->inst_imm); + ppc_subfc (code, ins->dreg, ppc_r11, ins->sreg1); + break; case CEE_SUB: ppc_subf (code, ins->dreg, ins->sreg2, ins->sreg1); break; @@ -2538,7 +2551,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_SBB_IMM: ppc_load (code, ppc_r11, ins->inst_imm); - ppc_subfe (code, ins->dreg, ins->sreg2, ppc_r11); + ppc_subfe (code, ins->dreg, ppc_r11, ins->sreg1); break; case OP_PPC_SUBFIC: g_assert (ppc_is_imm16 (ins->inst_imm)); @@ -2686,7 +2699,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) */ ppc_mulhwu (code, ppc_r0, ins->sreg1, ins->sreg2); ppc_cmpi (code, 0, 0, ppc_r0, 0); - EMIT_COND_SYSTEM_EXCEPTION (CEE_BNE_UN - CEE_BEQ, ins->inst_p1); + EMIT_COND_SYSTEM_EXCEPTION (CEE_BNE_UN - CEE_BEQ, "OverflowException"); ppc_mullw (code, ins->dreg, ins->sreg1, ins->sreg2); break; case OP_ICONST: @@ -3409,6 +3422,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) ArgInfo *ainfo = cinfo->args + i; inst = cfg->varinfo [pos]; + if (cfg->verbose_level > 2) + g_print ("Saving argument %d (type: %d)\n", i, ainfo->regtype); if (inst->opcode == OP_REGVAR) { if (ainfo->regtype == RegTypeGeneral) ppc_mr (code, inst->dreg, ainfo->reg); diff --git a/mono/mini/mini-s390.c b/mono/mini/mini-s390.c index 101c5c7ec76..6d7f7ce718b 100644 --- a/mono/mini/mini-s390.c +++ b/mono/mini/mini-s390.c @@ -2944,6 +2944,8 @@ guint8 cond; code = cfg->native_code + offset; } + mono_debug_record_line_number (cfg, ins, offset); + switch (ins->opcode) { case OP_STOREI1_MEMBASE_IMM: { s390_lhi (code, s390_r14, ins->inst_imm); @@ -3226,6 +3228,7 @@ guint8 cond; s390_alcr (code, ins->dreg, ins->sreg2); } break; + case OP_ADDCC_IMM: case OP_ADD_IMM: { if ((ins->next) && (ins->next->opcode == OP_ADC_IMM)) { @@ -3291,6 +3294,7 @@ guint8 cond; s390_slbr (code, ins->dreg, ins->sreg2); } break; + case OP_SUBCC_IMM: case OP_SUB_IMM: { if (s390_is_imm16 (-ins->inst_imm)) { if (ins->dreg != ins->sreg1) { diff --git a/mono/mini/mini-sparc.c b/mono/mini/mini-sparc.c index 54fd7fda138..1552e50c16e 100644 --- a/mono/mini/mini-sparc.c +++ b/mono/mini/mini-sparc.c @@ -2546,6 +2546,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code_start = (guint8*)code; // if (ins->cil_code) // g_print ("cil code\n"); + mono_debug_record_line_number (cfg, ins, offset); switch (ins->opcode) { case OP_STOREI1_MEMBASE_IMM: @@ -2651,6 +2652,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case CEE_ADD: sparc_add (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg); break; + case OP_ADDCC_IMM: case OP_ADD_IMM: /* according to inssel-long32.brg, this should set cc */ EMIT_ALU_IMM (ins, add, TRUE); @@ -2668,6 +2670,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case CEE_SUB: sparc_sub (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg); break; + case OP_SUBCC_IMM: case OP_SUB_IMM: /* according to inssel-long32.brg, this should set cc */ EMIT_ALU_IMM (ins, sub, TRUE); diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index 14710b31792..dc098a1c26b 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -1866,6 +1866,8 @@ mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) /* force source to be same as dest */ rs->iassign [ins->sreg1] = ins->dreg; rs->iassign [ins->sreg1 + 1] = ins->unused; + rs->isymbolic [ins->dreg] = ins->sreg1; + rs->isymbolic [ins->unused] = ins->sreg1 + 1; DEBUG (g_print ("\tassigned sreg1 (long) %s to sreg1 R%d\n", mono_arch_regname (ins->dreg), ins->sreg1)); DEBUG (g_print ("\tassigned sreg1 (long-high) %s to sreg1 R%d\n", mono_arch_regname (ins->unused), ins->sreg1 + 1)); @@ -2324,6 +2326,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_ADC: x86_alu_reg_reg (code, X86_ADC, ins->sreg1, ins->sreg2); break; + case OP_ADDCC_IMM: case OP_ADD_IMM: x86_alu_reg_imm (code, X86_ADD, ins->dreg, ins->inst_imm); break; @@ -2337,6 +2340,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_SBB: x86_alu_reg_reg (code, X86_SBB, ins->sreg1, ins->sreg2); break; + case OP_SUBCC_IMM: case OP_SUB_IMM: x86_alu_reg_imm (code, X86_SUB, ins->dreg, ins->inst_imm); break; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index d1e340a5966..28f70d463c3 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -1581,23 +1581,24 @@ mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins) */ static int handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int count) { - int i; + int i, bindex; MonoBasicBlock *outb; MonoInst *inst, **locals; + gboolean found; if (!count) return 0; if (cfg->verbose_level > 3) g_print ("%d item(s) on exit from B%d\n", count, bb->block_num); if (!bb->out_scount) { - int found = 0; bb->out_scount = count; //g_print ("bblock %d has out:", bb->block_num); + found = FALSE; for (i = 0; i < bb->out_count; ++i) { outb = bb->out_bb [i]; //g_print (" %d", outb->block_num); if (outb->in_stack) { - found = 1; + found = TRUE; bb->out_stack = outb->in_stack; break; } @@ -1606,19 +1607,34 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun if (!found) { bb->out_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count); for (i = 0; i < count; ++i) { -/* see bug#58863, but removing this code causes regressions in gtk-sharp build - * (SEGV running Method::Initialize() in gapi_codegen.exe) - */ -#if 1 - /* try to reuse temps already allocated for this purpouse, if they occupy the same - * stack slot and if they are of the same type. */ - bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]); -#else - bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL); -#endif + /* + * try to reuse temps already allocated for this purpouse, if they occupy the same + * stack slot and if they are of the same type. + * This won't cause conflicts since if 'local' is used to + * store one of the values in the in_stack of a bblock, then + * the same variable will be used for the same outgoing stack + * slot as well. + * This doesn't work when inlining methods, since the bblocks + * in the inlined methods do not inherit their in_stack from + * the bblock they are inlined to. See bug #58863 for an + * example. + */ + if (cfg->inlined_method) + bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL); + else + bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]); } } } + + for (i = 0; i < bb->out_count; ++i) { + outb = bb->out_bb [i]; + if (outb->in_scount) + continue; /* check they are the same locals */ + outb->in_scount = count; + outb->in_stack = bb->out_stack; + } + locals = bb->out_stack; for (i = 0; i < count; ++i) { /* add store ops at the end of the bb, before the branch */ @@ -1633,14 +1649,36 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun if (cfg->verbose_level > 3) g_print ("storing %d to temp %d\n", i, locals [i]->inst_c0); } - - for (i = 0; i < bb->out_count; ++i) { - outb = bb->out_bb [i]; - if (outb->in_scount) - continue; /* check they are the same locals */ - outb->in_scount = count; - outb->in_stack = locals; + + /* + * It is possible that the out bblocks already have in_stack assigned, and + * the in_stacks differ. In this case, we will store to all the different + * in_stacks. + */ + + found = TRUE; + bindex = 0; + while (found) { + /* Find a bblock which has a different in_stack */ + found = FALSE; + while (bindex < bb->out_count) { + outb = bb->out_bb [bindex]; + if (outb->in_stack != locals) { + /* + * Instead of storing sp [i] to locals [i], we need to store + * locals [i] to <new locals>[i], since the sp [i] tree can't + * be shared between trees. + */ + for (i = 0; i < count; ++i) + mono_add_varcopy_to_end (cfg, bb, locals [i]->inst_c0, outb->in_stack [i]->inst_c0); + locals = outb->in_stack; + found = TRUE; + break; + } + bindex ++; + } } + return 0; } @@ -2427,6 +2465,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoMethodHeader *cheader; MonoBasicBlock *ebblock, *sbblock; int i, costs, new_locals_offset; + MonoMethod *prev_inlined_method; if (cfg->verbose_level > 2) g_print ("INLINE START %p %s -> %s\n", cmethod, mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE)); @@ -2455,8 +2494,13 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, ebblock->block_num = cfg->num_bblocks++; ebblock->real_offset = real_offset; + prev_inlined_method = cfg->inlined_method; + cfg->inlined_method = cmethod; + costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, new_locals_offset, rvar, dont_inline, sp, real_offset, *ip == CEE_CALLVIRT); + cfg->inlined_method = prev_inlined_method; + if ((costs >= 0 && costs < 60) || inline_allways) { if (cfg->verbose_level > 2) g_print ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE)); @@ -3849,7 +3893,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b CHECK_OPSIZE (5); n = read32 (ip + 1); - if (method->wrapper_type != MONO_WRAPPER_NONE) { + if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) { + NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n)); + ins->cil_code = ip; + ins->type = STACK_OBJ; + *sp = ins; + } + else if (method->wrapper_type != MONO_WRAPPER_NONE) { int temp; MonoInst *iargs [1]; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index adc1e9086b5..e62be1b95cb 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -492,6 +492,7 @@ typedef struct { MonoSpillInfo *spill_info_float; /* fp register spills */ gint spill_count; /* unsigned char *cil_code; */ + MonoMethod *inlined_method; /* the method which is currently inlined */ /* the exception object passed to catch/filter blocks */ MonoInst *exvar; diff --git a/mono/tests/ChangeLog b/mono/tests/ChangeLog index e73b632c1c1..041938869bd 100644 --- a/mono/tests/ChangeLog +++ b/mono/tests/ChangeLog @@ -1,3 +1,9 @@ +2004-09-07 Duncan Mak <duncan@ximian.com> + + * typeof-ptr.cs: Add unsafe sections to the code that's using + pointers directly. This was breaking the test stage on the build + boxes. + 2004-05-29 Zoltan Varga <vargaz@freemail.hu> * invoke.cs: Add an Invoke test. diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 23cc36cc3cc..2ac008e74c4 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -41,6 +41,7 @@ TEST_CS_SRC= \ exception16.cs \ struct.cs \ valuetype-gettype.cs \ + typeof-ptr.cs \ static-constructor.cs \ pinvoke.cs \ pinvoke1.cs \ diff --git a/mono/tests/typeof-ptr.cs b/mono/tests/typeof-ptr.cs new file mode 100644 index 00000000000..69e75ca1745 --- /dev/null +++ b/mono/tests/typeof-ptr.cs @@ -0,0 +1,26 @@ +using System; +using System.Reflection; + +class T { + public static unsafe void meth (int a, int* b) { + } + static int Main () { + ParameterInfo[] args = typeof (T).GetMethod ("meth").GetParameters (); + if (args[0].ParameterType == args[1].ParameterType) + return 1; + + unsafe { + if (typeof(int) == typeof (int*)) + return 2; + } + if (args[0].ParameterType != typeof(int)) + return 3; + + unsafe { + if (args[1].ParameterType != typeof(int*)) + return 4; + } + + return 0; + } +} diff --git a/tools/locale-builder/supp/ChangeLog b/tools/locale-builder/supp/ChangeLog index b5eb13b4ddc..aac15bd01ce 100755 --- a/tools/locale-builder/supp/ChangeLog +++ b/tools/locale-builder/supp/ChangeLog @@ -1,3 +1,9 @@ +2004-10-06 Jackson Harper <jackson@ximian.com> + + * pt.xml: We need a space after R$. Is there a better way to do + this? I should know... + * pt_BR.xml: Fix currency format. + 2004-06-08 Atsushi Enomoto <atsushi@ximian.com> * ja.xml : added extra datetime patterns. diff --git a/tools/locale-builder/supp/pt.xml b/tools/locale-builder/supp/pt.xml new file mode 100755 index 00000000000..c424d37d4fa --- /dev/null +++ b/tools/locale-builder/supp/pt.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<ldml> + <numbers> + <currencies> + <currency type="BRL"> + <displayName>Real Brasileiro</displayName> + <symbol>R$ </symbol> + </currency> + </currencies> + </numbers> +</ldml> + diff --git a/tools/locale-builder/supp/pt_BR.xml b/tools/locale-builder/supp/pt_BR.xml index 5492f0a75b8..f06421234f3 100755 --- a/tools/locale-builder/supp/pt_BR.xml +++ b/tools/locale-builder/supp/pt_BR.xml @@ -4,7 +4,7 @@ <currencyFormats> <currencyFormatLength > <currencyFormat > - <pattern>#,##0;(-#,##0)</pattern> + <pattern>#,##0.00;(#,##0.00)</pattern> </currencyFormat> </currencyFormatLength > </currencyFormats> diff --git a/web/download b/web/download index 6a9789d3744..3992312f61f 100644 --- a/web/download +++ b/web/download @@ -14,21 +14,123 @@ Online API documentation for Mono is available in the `monodoc' package. - Gtk-sharp is package to build GUI applications with the Gtk toolkit. - + Gtk# is package to build GUI applications with the Gtk+ toolkit. The software is also available on the `Mono' channel in <a href="http://www.ximian.com/products/redcarpet/">Red Carpet</a>. - Some useful links: the <a - href="http://www.go-mono.org/faq.html">FAQ</a>. - - Packages can find RPM Spec files and other resources in the <a + Packagers can find RPM Spec files and other resources in the <a href="http://www.go-mono.com/packagers/">packagers page</a>. <table> <tbody> <tr bgcolor="#DDDDDD"> <td> + <b>Mono 1.0</b><br> + <a href="archive/1.0/index.html">Release notes</a><br> + June 30th, 2004 + </td> + <td> + <table cellspacing="1" cellpadding="3"> + <tr bgcolor="#BBBBBB"> + <td> + <b>Source Code</b> + </td> + <td> + <ul> + <li><a href="archive/1.0/mono-1.0.tar.gz">Mono Runtime 1.0</a> + <li><a href="archive/1.0/mcs-1.0.tar.gz">Mono Class Libraries and C# Compiler 1.0</a> + <li><a href="archive/1.0/libgdiplus-1.0.tar.gz">libgdiplus 1.0</a> + <p> + <li><a href="archive/1.0/monodoc-1.0.tar.gz">MonoDoc 1.0</a> + <li><a href="archive/1.0/xsp-1.0.tar.gz">XSP web server 1.0</a> + <li><a href="archive/1.0/mod_mono-1.0.tar.gz">Apache Mono module 1.0</a> + <p> + <li><a href="archive/1.0/winelib-0.3.tar.gz">Winelib 0.3</a> + <p> + <li><a href="archive/1.0/gtk-sharp-1.0.tar.gz">Gtk# 1.0</a> + <li><a href="archive/1.0/gecko-sharp-0.5.tar.gz">Gecko# 0.5</a> + <li><a href="archive/1.0/gtksourceview-sharp-0.5.tar.gz">Gtk SourceView# 0.5</a> + <li><a href="archive/1.0/monodevelop-0.5.tar.gz">MonoDevelop IDE 0.5</a> + </ul> + </td> + </tr> + <tr bgcolor="#bbbbbb"> + <td bgcolor="#999999"> + <img src="images/redhat-36.gif"><b>Red Hat 9.0/x86</b><br> + </td> + <td> + <a href="archive/1.0/redhat-9-i386">Packages</a> + </td> + </tr> + <tr bgcolor="#bbbbbb"> + <td bgcolor="#999999"> + <img src="images/redhat-36.gif"><b>Fedora Core 1/x86</b><br> + </td> + <td> + <a href="archive/1.0/fedora-1-i386">Packages</a> + <p><a href="http://www.go-mono.com/archive/yum-repository/fedora-1-i386">YUM Repository</a> + </td> + </tr> + <tr bgcolor="#bbbbbb"> + <td bgcolor="#999999"> + <img src="images/redhat-36.gif"><b>Fedora Core 2/x86</b><br> + </td> + <td> + <a href="archive/1.0/fedora-2-i386">Packages</a> + <p><a href="http://www.go-mono.com/archive/yum-repository/fedora-2-i386">YUM Repository</a> + </td> + </tr> + <tr bgcolor="#bbbbbb"> + <td bgcolor="#999999"> + <img src="images/suse-36.gif"><b>SLES 8/x86</b><br> + </td> + <td> + <a href="archive/1.0/sles-8-i386/">Packages</a> + </td> + </tr> + <tr bgcolor="#bbbbbb"> + <td bgcolor="#999999"> + <img src="images/suse-36.gif"><b>SUSE 9/x86</b><br> + </td> + <td> + <a href="archive/1.0/suse-90-i586/">Packages</a> + </td> + </tr> + <tr bgcolor="#bbbbbb"> + <td bgcolor="#999999"> + <img src="images/suse-36.gif"><b>SUSE 9.1/x86</b><br> + </td> + <td> + <a href="archive/1.0/suse-91-i586/">Packages</a> + </td> + </tr> + <tr> + <td bgcolor="#999999"> + <div align="left"><img src="images/windows-36.gif"></div> + <div align="right"><b>Windows installer</b><br><small>Win2k and above</small></div> + </td> + <td> + <a href="archive/1.0/windows/mono-1.0-win32-1.exe">Mono Setup</a> + </td> + </tr> + <tr> + <td bgcolor="#999999"> + <img src="images/macos-36.gif"><b>Mac OS X package</b> + </td> + <td> + <a href="archive/1.0/macos/MonoFramework-1.0.dmg">MonoFramework-1.0.dmg</a> in /Library/Framework + </td> + </tr> + </table> + </td> + </table> + + <hr> + + <table> + <tbody> + <tr bgcolor="#DDDDDD"> + <td> <b>Release Candidate</b><br> <!-- <a href="archive/beta3/beta3.html">Release notes</a><br> --> June 25th, 2004 diff --git a/web/index b/web/index index d701c09c4d5..52a8ced8b09 100644 --- a/web/index +++ b/web/index @@ -1,3 +1,4 @@ +<meta http-equiv="Refresh" content="0"; URL=http://www.mono-project.com/"> <link rel="alternate" type="application/rss+xml" title="RSS" href="index.rss"/> @@ -174,6 +175,26 @@ </a> Wikis. </p> +@item Jun 30th, 2004: Mono 1.0 + + <table> + <tr> + <td> + <img + src="http://www.go-mono.com/archive/1.0/mono1.gif"></td> + <td> + <b>Mono 1.0 has been released!</b><br/> + + <p>Be the first kid in your block to install the + <i>it-took-us-three-years-but-we-did-it</i> development platform. + + <p>Read the <a + href="http://www.go-mono.com/archive/1.0/index.html">release notes</a> + or <a href="http://www.go-mono.com/download.html">download it</a></p> + </td> + </tr> + </table> + @item Jun 23rd, 2004: The Mono Hackers Hall of Fame welcomes John Luke, Dan Morgan and Tim Coleman. The <a href="http://www.go-mono.com/hackers.html">Mono Hackers Hall Of Fame</a> |