| //===-------------- Mono.cpp - The Mono interface -------------------------===// |
| // |
| // N3 |
| // |
| // This file is licensed under the University of Illinois Open Source License |
| // and the Mono License. See LICENSE.TXT for details. |
| // The file also has the following additional copyright: |
| // |
| // (C) 2008 Ximian, Inc. http://www.ximian.com |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "mvm/JIT.h" |
| |
| #include "Assembly.h" |
| #include "MonoString.h" |
| #include "MSCorlib.h" |
| #include "N3.h" |
| #include "Reader.h" |
| #include "VMArray.h" |
| #include "VMClass.h" |
| #include "VMObject.h" |
| #include "VMThread.h" |
| |
| #include <glib.h> |
| |
| #include "number-formatter.h" |
| |
| #include "MonoPath.inc" |
| |
| using namespace n3; |
| |
| extern "C" int System_Environment_get_Platform (void) { |
| #if defined (PLATFORM_WIN32) |
| /* Win32NT */ |
| return 2; |
| #else |
| /* Unix */ |
| return 128; |
| #endif |
| } |
| |
| static const char *encodings [] = { |
| (char *) 1, |
| "ascii", "us_ascii", "us", "ansi_x3.4_1968", |
| "ansi_x3.4_1986", "cp367", "csascii", "ibm367", |
| "iso_ir_6", "iso646_us", "iso_646.irv:1991", |
| (char *) 2, |
| "utf_7", "csunicode11utf7", "unicode_1_1_utf_7", |
| "unicode_2_0_utf_7", "x_unicode_1_1_utf_7", |
| "x_unicode_2_0_utf_7", |
| (char *) 3, |
| "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8", |
| "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8", |
| (char *) 4, |
| "utf_16", "UTF_16LE", "ucs_2", "unicode", |
| "iso_10646_ucs2", |
| (char *) 5, |
| "unicodefffe", "utf_16be", |
| (char *) 6, |
| "iso_8859_1", |
| (char *) 0 |
| }; |
| |
| /* |
| * Returns the internal codepage, if the value of "int_code_page" is |
| * 1 at entry, and we can not compute a suitable code page number, |
| * returns the code page as a string |
| */ |
| extern "C" MonoString* |
| System_Text_Encoding_InternalCodePage (gint32 *int_code_page) |
| { |
| const char *cset; |
| const char *p; |
| char *c; |
| char *codepage = NULL; |
| int code; |
| int want_name = *int_code_page; |
| int i; |
| |
| *int_code_page = -1; |
| |
| g_get_charset (&cset); |
| c = codepage = strdup (cset); |
| for (c = codepage; *c; c++){ |
| if (isascii (*c) && isalpha (*c)) |
| *c = tolower (*c); |
| if (*c == '-') |
| *c = '_'; |
| } |
| /* g_print ("charset: %s\n", cset); */ |
| |
| /* handle some common aliases */ |
| p = encodings [0]; |
| code = 0; |
| for (i = 0; p != 0; ){ |
| if ((gssize) p < 7){ |
| code = (gssize) p; |
| p = encodings [++i]; |
| continue; |
| } |
| if (strcmp (p, codepage) == 0){ |
| *int_code_page = code; |
| break; |
| } |
| p = encodings [++i]; |
| } |
| |
| if (strstr (codepage, "utf_8") != NULL) |
| *int_code_page |= 0x10000000; |
| free (codepage); |
| |
| if (want_name && *int_code_page == -1) { |
| N3 *vm = (N3*)VMThread::get()->getVM(); |
| declare_gcroot(ArrayChar*, array_res) = vm->asciizToArray(cset); |
| declare_gcroot(MonoString*, res) = (MonoString*)(vm->arrayToString(array_res)); |
| return res; |
| } else |
| return NULL; |
| } |
| |
| extern "C" void System_Threading_Monitor_Monitor_exit(VMObject* obj) { |
| // TODO: There's a bug in the bootstrap, see why |
| llvm_gcroot(obj, 0); |
| if (LockObj::owner(obj->lockObj)) VMObject::unlock(obj); |
| } |
| |
| extern "C" bool System_Threading_Monitor_Monitor_try_enter(VMObject* obj, int ms) { |
| llvm_gcroot(obj, 0); |
| VMObject::aquire(obj); |
| return true; |
| } |
| |
| |
| extern "C" void* System_IO_MonoIO_get_ConsoleError() { |
| return (void*)stderr; |
| } |
| |
| extern "C" void* System_IO_MonoIO_get_ConsoleOutput() { |
| return (void*)stdout; |
| } |
| |
| extern "C" void* System_IO_MonoIO_get_ConsoleInput() { |
| return (void*)stdin; |
| } |
| |
| enum MonoFileType { |
| Unknown=0x0000, |
| Disk=0x0001, |
| Char=0x0002, |
| Pipe=0x0003, |
| Remote=0x8000 |
| }; |
| |
| extern "C" MonoFileType System_IO_MonoIO_GetFileType(void* handle, int* error) { |
| if (handle == (void*)stdin || handle == (void*)stdout || handle == (void*)stderr) |
| return Char; |
| else |
| return Unknown; |
| } |
| |
| extern "C" MonoString * |
| System_Environment_get_NewLine (void) |
| { |
| N3 *vm = (N3*)VMThread::get()->getVM(); |
| #if defined (PLATFORM_WIN32) |
| declare_gcroot(ArrayChar*, array) = vm->asciizToArray("\r\n"); |
| #else |
| declare_gcroot(ArrayChar*, array) = vm->asciizToArray("\n"); |
| #endif |
| |
| declare_gcroot(MonoString*, res) = (MonoString*)vm->arrayToString(array); |
| return res; |
| } |
| |
| extern "C" void |
| System_String_InternalCopyTo(MonoString* str, sint32 sindex, VMArray* dest, sint32 destIndex, sint32 count) { |
| llvm_gcroot(str, 0); |
| llvm_gcroot(dest, 0); |
| declare_gcroot(const ArrayChar*, contents) = str->value; |
| memcpy(&dest->elements[destIndex], &contents->elements[sindex], count * sizeof(uint16)); |
| } |
| |
| extern "C" uint16 System_String_get_Chars(MonoString* str, sint32 offset) { |
| llvm_gcroot(str, 0); |
| return str->value->elements[offset]; |
| } |
| |
| static sint32 byteLength(VMArray* array) { |
| llvm_gcroot(array, 0); |
| VMClassArray* cl = (VMClassArray*)array->classOf; |
| VMCommonClass* base = cl->baseClass; |
| uint32 size = base->naturalType->getPrimitiveSizeInBits() / 8; |
| return array->size * size; |
| } |
| |
| extern "C" bool System_Buffer_BlockCopyInternal (VMArray* src, int src_offset, VMArray* dest, int dest_offset, int count) { |
| llvm_gcroot(src, 0); |
| llvm_gcroot(dest, 0); |
| uint8 *src_buf, *dest_buf; |
| |
| /* watch out for integer overflow */ |
| if ((src_offset > byteLength(src) - count) || (dest_offset > byteLength(dest) - count)) |
| return false; |
| |
| src_buf = (uint8 *)src->elements + src_offset; |
| dest_buf = (uint8 *)dest->elements + dest_offset; |
| |
| if (src != dest) |
| memcpy (dest_buf, src_buf, count); |
| else |
| memmove (dest_buf, src_buf, count); /* Source and dest are the same array */ |
| |
| return true; |
| |
| } |
| |
| extern "C" sint32 System_Buffer_ByteLengthInternal(VMArray* array) { |
| llvm_gcroot(array, 0); |
| return byteLength(array); |
| } |
| |
| extern "C" sint32 |
| System_IO_MonoIO_Write (void* handle, ArrayUInt8 *src, |
| sint32 src_offset, sint32 count, |
| sint32 *error) |
| { |
| llvm_gcroot(src, 0); |
| char* buffer = (char*)alloca( 1024);//(count + 8) * sizeof(uint16)); |
| uint32 n = 0; |
| |
| *error = 0; |
| |
| if (src_offset + count > src->size) |
| return 0; |
| |
| memcpy(buffer, (char*)&(src->elements[src_offset]), count); |
| buffer[count] = 0; |
| n = fprintf((FILE*)handle, buffer); |
| |
| return (sint32)n; |
| } |
| |
| /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */ |
| extern "C" void |
| System_NumberFormatter_GetFormatterTables (guint64 const **mantissas, |
| gint32 const **exponents, |
| gunichar2 const **digitLowerTable, |
| gunichar2 const **digitUpperTable, |
| gint64 const **tenPowersList, |
| gint32 const **decHexDigits) |
| { |
| *mantissas = Formatter_MantissaBitsTable; |
| *exponents = Formatter_TensExponentTable; |
| *digitLowerTable = Formatter_DigitLowerTable; |
| *digitUpperTable = Formatter_DigitUpperTable; |
| *tenPowersList = Formatter_TenPowersList; |
| *decHexDigits = Formatter_DecHexDigits; |
| } |
| |
| extern "C" VMObject* System_Threading_Thread_CurrentThread_internal() { |
| declare_gcroot(VMObject*, appThread) = VMThread::get()->ooo_appThread; |
| return appThread; |
| } |
| |
| extern "C" VMObject* |
| System_Threading_Thread_GetCachedCurrentCulture (VMObject *obj) |
| { |
| llvm_gcroot(obj, 0); |
| return 0; |
| } |
| |
| extern "C" VMObject* |
| System_Threading_Thread_GetSerializedCurrentCulture (VMObject *obj) |
| { |
| llvm_gcroot(obj, 0); |
| return 0; |
| } |
| |
| extern "C" VMObject* System_Object_MemberwiseClone(VMObject* obj) { |
| llvm_gcroot(obj, 0); |
| uint64 size = obj->objectSize(); |
| declare_gcroot(VMObject*, res) = ((VMClass*)obj->classOf)->doNew(); |
| memcpy(res, obj, size); |
| res->lockObj = 0; |
| return res; |
| } |
| |
| extern "C" bool |
| System_Globalization_CultureInfo_construct_internal_locale_from_current_locale (VMObject *ci) |
| { |
| llvm_gcroot(ci, 0); |
| return false; |
| } |
| |
| extern "C" void |
| System_Threading_Thread_SetCachedCurrentCulture (VMObject* thread, VMObject *culture) |
| { |
| llvm_gcroot(thread, 0); |
| llvm_gcroot(culture, 0); |
| } |
| |
| extern "C" void |
| System_String__ctor(MonoString* str, ArrayChar* array, sint32 startIndex, sint32 count) { |
| llvm_gcroot(str, 0); |
| llvm_gcroot(array, 0); |
| N3* vm = VMThread::get()->getVM(); |
| declare_gcroot(const ArrayChar*, value) = vm->bufToArray(&(array->elements[startIndex]), count); |
| str->length = count; |
| str->startChar = array->elements[startIndex]; |
| str->value = value; |
| } |
| |
| extern "C" MonoString * |
| System_String_InternalJoin (MonoString *separator, VMArray * value, sint32 sindex, sint32 count) |
| { |
| llvm_gcroot(separator, 0); |
| llvm_gcroot(value, 0); |
| declare_gcroot(MonoString*, current) = 0; |
| sint32 length; |
| sint32 pos; |
| sint32 insertlen; |
| sint32 destpos; |
| sint32 srclen; |
| const uint16 *insert; |
| const uint16 *src; |
| uint16 *dest; |
| |
| insert = separator->value->elements; |
| insertlen = separator->length; |
| |
| length = 0; |
| for (pos = sindex; pos != sindex + count; pos++) { |
| current = (MonoString*)value->elements[pos]; |
| if (current != NULL) |
| length += current->length; |
| |
| if (pos < sindex + count - 1) |
| length += insertlen; |
| } |
| |
| dest = (uint16*)alloca(length * sizeof(uint16)); |
| destpos = 0; |
| |
| for (pos = sindex; pos != sindex + count; pos++) { |
| current = (MonoString*)value->elements[pos]; |
| if (current != NULL) { |
| src = current->value->elements; |
| srclen = current->length; |
| |
| memcpy (dest + destpos, src, srclen * sizeof(uint16)); |
| destpos += srclen; |
| } |
| |
| if (pos < sindex + count - 1) { |
| memcpy(dest + destpos, insert, insertlen * sizeof(uint16)); |
| destpos += insertlen; |
| } |
| } |
| |
| N3* vm = (N3*)VMThread::get()->getVM(); |
| declare_gcroot(const ArrayChar*, array) = vm->bufToArray(dest, length); |
| declare_gcroot(MonoString*, res) = (MonoString*)vm->arrayToString(array); |
| return res; |
| } |
| |
| extern "C" MonoString * |
| System_String_InternalAllocateStr (sint32 length) |
| { |
| declare_gcroot(MonoString*, str) = (MonoString*)MSCorlib::pString->doNew(); |
| str->length = length; |
| return str; |
| } |
| |